1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker
5*bb4ee6a4SAndroid Build Coastguard Worker use std::cmp::Ordering;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::convert::TryFrom;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::io;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::mem;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::thread::JoinHandleExt;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null_mut;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::result;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::thread::JoinHandle;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
15*bb4ee6a4SAndroid Build Coastguard Worker
16*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_int;
17*bb4ee6a4SAndroid Build Coastguard Worker use libc::pthread_kill;
18*bb4ee6a4SAndroid Build Coastguard Worker use libc::pthread_sigmask;
19*bb4ee6a4SAndroid Build Coastguard Worker use libc::pthread_t;
20*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigaction;
21*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigaddset;
22*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigemptyset;
23*bb4ee6a4SAndroid Build Coastguard Worker use libc::siginfo_t;
24*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigismember;
25*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigpending;
26*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigset_t;
27*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigtimedwait;
28*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigwait;
29*bb4ee6a4SAndroid Build Coastguard Worker use libc::timespec;
30*bb4ee6a4SAndroid Build Coastguard Worker use libc::EAGAIN;
31*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINTR;
32*bb4ee6a4SAndroid Build Coastguard Worker use libc::EINVAL;
33*bb4ee6a4SAndroid Build Coastguard Worker use libc::SA_RESTART;
34*bb4ee6a4SAndroid Build Coastguard Worker use libc::SIG_BLOCK;
35*bb4ee6a4SAndroid Build Coastguard Worker use libc::SIG_DFL;
36*bb4ee6a4SAndroid Build Coastguard Worker use libc::SIG_UNBLOCK;
37*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
38*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error;
39*bb4ee6a4SAndroid Build Coastguard Worker
40*bb4ee6a4SAndroid Build Coastguard Worker use super::errno_result;
41*bb4ee6a4SAndroid Build Coastguard Worker use super::Error as ErrnoError;
42*bb4ee6a4SAndroid Build Coastguard Worker use super::Pid;
43*bb4ee6a4SAndroid Build Coastguard Worker use super::Result;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::handle_eintr_errno;
45*bb4ee6a4SAndroid Build Coastguard Worker use crate::handle_eintr_rc;
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::unix::duration_to_timespec;
47*bb4ee6a4SAndroid Build Coastguard Worker
48*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
49*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)]
50*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error {
51*bb4ee6a4SAndroid Build Coastguard Worker /// The signal could not be blocked.
52*bb4ee6a4SAndroid Build Coastguard Worker #[error("signal could not be blocked: {0}")]
53*bb4ee6a4SAndroid Build Coastguard Worker BlockSignal(ErrnoError),
54*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to check if given signal is in the set of pending signals.
55*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to check whether given signal is in the pending set: {0}")]
56*bb4ee6a4SAndroid Build Coastguard Worker ClearCheckPending(ErrnoError),
57*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to get pending signals.
58*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to get pending signals: {0}")]
59*bb4ee6a4SAndroid Build Coastguard Worker ClearGetPending(ErrnoError),
60*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to wait for given signal.
61*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to wait for given signal: {0}")]
62*bb4ee6a4SAndroid Build Coastguard Worker ClearWaitPending(ErrnoError),
63*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to check if the requested signal is in the blocked set already.
64*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to check whether requested signal is in the blocked set: {0}")]
65*bb4ee6a4SAndroid Build Coastguard Worker CompareBlockedSignals(ErrnoError),
66*bb4ee6a4SAndroid Build Coastguard Worker /// Couldn't create a sigset.
67*bb4ee6a4SAndroid Build Coastguard Worker #[error("couldn't create a sigset: {0}")]
68*bb4ee6a4SAndroid Build Coastguard Worker CreateSigset(ErrnoError),
69*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to get session id.
70*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to get session id: {0}")]
71*bb4ee6a4SAndroid Build Coastguard Worker GetSid(ErrnoError),
72*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to send signal to pid.
73*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to send signal: {0}")]
74*bb4ee6a4SAndroid Build Coastguard Worker Kill(ErrnoError),
75*bb4ee6a4SAndroid Build Coastguard Worker /// The signal mask could not be retrieved.
76*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to retrieve signal mask: {}", io::Error::from_raw_os_error(*.0))]
77*bb4ee6a4SAndroid Build Coastguard Worker RetrieveSignalMask(i32),
78*bb4ee6a4SAndroid Build Coastguard Worker /// Converted signum greater than SIGRTMAX.
79*bb4ee6a4SAndroid Build Coastguard Worker #[error("got RT signal greater than max: {0:?}")]
80*bb4ee6a4SAndroid Build Coastguard Worker RtSignumGreaterThanMax(Signal),
81*bb4ee6a4SAndroid Build Coastguard Worker /// The wrapped signal has already been blocked.
82*bb4ee6a4SAndroid Build Coastguard Worker #[error("signal {0} already blocked")]
83*bb4ee6a4SAndroid Build Coastguard Worker SignalAlreadyBlocked(c_int),
84*bb4ee6a4SAndroid Build Coastguard Worker /// Timeout reached.
85*bb4ee6a4SAndroid Build Coastguard Worker #[error("timeout reached.")]
86*bb4ee6a4SAndroid Build Coastguard Worker TimedOut,
87*bb4ee6a4SAndroid Build Coastguard Worker /// The signal could not be unblocked.
88*bb4ee6a4SAndroid Build Coastguard Worker #[error("signal could not be unblocked: {0}")]
89*bb4ee6a4SAndroid Build Coastguard Worker UnblockSignal(ErrnoError),
90*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to convert signum to Signal.
91*bb4ee6a4SAndroid Build Coastguard Worker #[error("unrecoginized signal number: {0}")]
92*bb4ee6a4SAndroid Build Coastguard Worker UnrecognizedSignum(i32),
93*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to wait for signal.
94*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to wait for signal: {0}")]
95*bb4ee6a4SAndroid Build Coastguard Worker WaitForSignal(ErrnoError),
96*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to wait for pid.
97*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to wait for process: {0}")]
98*bb4ee6a4SAndroid Build Coastguard Worker WaitPid(ErrnoError),
99*bb4ee6a4SAndroid Build Coastguard Worker }
100*bb4ee6a4SAndroid Build Coastguard Worker
101*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug, Eq, PartialEq)]
102*bb4ee6a4SAndroid Build Coastguard Worker #[repr(i32)]
103*bb4ee6a4SAndroid Build Coastguard Worker pub enum Signal {
104*bb4ee6a4SAndroid Build Coastguard Worker Abort = libc::SIGABRT,
105*bb4ee6a4SAndroid Build Coastguard Worker Alarm = libc::SIGALRM,
106*bb4ee6a4SAndroid Build Coastguard Worker Bus = libc::SIGBUS,
107*bb4ee6a4SAndroid Build Coastguard Worker Child = libc::SIGCHLD,
108*bb4ee6a4SAndroid Build Coastguard Worker Continue = libc::SIGCONT,
109*bb4ee6a4SAndroid Build Coastguard Worker ExceededFileSize = libc::SIGXFSZ,
110*bb4ee6a4SAndroid Build Coastguard Worker FloatingPointException = libc::SIGFPE,
111*bb4ee6a4SAndroid Build Coastguard Worker HangUp = libc::SIGHUP,
112*bb4ee6a4SAndroid Build Coastguard Worker IllegalInstruction = libc::SIGILL,
113*bb4ee6a4SAndroid Build Coastguard Worker Interrupt = libc::SIGINT,
114*bb4ee6a4SAndroid Build Coastguard Worker Io = libc::SIGIO,
115*bb4ee6a4SAndroid Build Coastguard Worker Kill = libc::SIGKILL,
116*bb4ee6a4SAndroid Build Coastguard Worker Pipe = libc::SIGPIPE,
117*bb4ee6a4SAndroid Build Coastguard Worker Power = libc::SIGPWR,
118*bb4ee6a4SAndroid Build Coastguard Worker Profile = libc::SIGPROF,
119*bb4ee6a4SAndroid Build Coastguard Worker Quit = libc::SIGQUIT,
120*bb4ee6a4SAndroid Build Coastguard Worker SegmentationViolation = libc::SIGSEGV,
121*bb4ee6a4SAndroid Build Coastguard Worker StackFault = libc::SIGSTKFLT,
122*bb4ee6a4SAndroid Build Coastguard Worker Stop = libc::SIGSTOP,
123*bb4ee6a4SAndroid Build Coastguard Worker Sys = libc::SIGSYS,
124*bb4ee6a4SAndroid Build Coastguard Worker Trap = libc::SIGTRAP,
125*bb4ee6a4SAndroid Build Coastguard Worker Terminate = libc::SIGTERM,
126*bb4ee6a4SAndroid Build Coastguard Worker TtyIn = libc::SIGTTIN,
127*bb4ee6a4SAndroid Build Coastguard Worker TtyOut = libc::SIGTTOU,
128*bb4ee6a4SAndroid Build Coastguard Worker TtyStop = libc::SIGTSTP,
129*bb4ee6a4SAndroid Build Coastguard Worker Urgent = libc::SIGURG,
130*bb4ee6a4SAndroid Build Coastguard Worker User1 = libc::SIGUSR1,
131*bb4ee6a4SAndroid Build Coastguard Worker User2 = libc::SIGUSR2,
132*bb4ee6a4SAndroid Build Coastguard Worker VtAlarm = libc::SIGVTALRM,
133*bb4ee6a4SAndroid Build Coastguard Worker Winch = libc::SIGWINCH,
134*bb4ee6a4SAndroid Build Coastguard Worker Xcpu = libc::SIGXCPU,
135*bb4ee6a4SAndroid Build Coastguard Worker // Rt signal numbers are be adjusted in the conversion to integer.
136*bb4ee6a4SAndroid Build Coastguard Worker Rt0 = libc::SIGSYS + 1,
137*bb4ee6a4SAndroid Build Coastguard Worker Rt1,
138*bb4ee6a4SAndroid Build Coastguard Worker Rt2,
139*bb4ee6a4SAndroid Build Coastguard Worker Rt3,
140*bb4ee6a4SAndroid Build Coastguard Worker Rt4,
141*bb4ee6a4SAndroid Build Coastguard Worker Rt5,
142*bb4ee6a4SAndroid Build Coastguard Worker Rt6,
143*bb4ee6a4SAndroid Build Coastguard Worker Rt7,
144*bb4ee6a4SAndroid Build Coastguard Worker // Only 8 are guaranteed by POSIX, Linux has 32, but only 29 or 30 are usable.
145*bb4ee6a4SAndroid Build Coastguard Worker Rt8,
146*bb4ee6a4SAndroid Build Coastguard Worker Rt9,
147*bb4ee6a4SAndroid Build Coastguard Worker Rt10,
148*bb4ee6a4SAndroid Build Coastguard Worker Rt11,
149*bb4ee6a4SAndroid Build Coastguard Worker Rt12,
150*bb4ee6a4SAndroid Build Coastguard Worker Rt13,
151*bb4ee6a4SAndroid Build Coastguard Worker Rt14,
152*bb4ee6a4SAndroid Build Coastguard Worker Rt15,
153*bb4ee6a4SAndroid Build Coastguard Worker Rt16,
154*bb4ee6a4SAndroid Build Coastguard Worker Rt17,
155*bb4ee6a4SAndroid Build Coastguard Worker Rt18,
156*bb4ee6a4SAndroid Build Coastguard Worker Rt19,
157*bb4ee6a4SAndroid Build Coastguard Worker Rt20,
158*bb4ee6a4SAndroid Build Coastguard Worker Rt21,
159*bb4ee6a4SAndroid Build Coastguard Worker Rt22,
160*bb4ee6a4SAndroid Build Coastguard Worker Rt23,
161*bb4ee6a4SAndroid Build Coastguard Worker Rt24,
162*bb4ee6a4SAndroid Build Coastguard Worker Rt25,
163*bb4ee6a4SAndroid Build Coastguard Worker Rt26,
164*bb4ee6a4SAndroid Build Coastguard Worker Rt27,
165*bb4ee6a4SAndroid Build Coastguard Worker Rt28,
166*bb4ee6a4SAndroid Build Coastguard Worker Rt29,
167*bb4ee6a4SAndroid Build Coastguard Worker Rt30,
168*bb4ee6a4SAndroid Build Coastguard Worker Rt31,
169*bb4ee6a4SAndroid Build Coastguard Worker }
170*bb4ee6a4SAndroid Build Coastguard Worker
171*bb4ee6a4SAndroid Build Coastguard Worker impl From<Signal> for c_int {
from(signal: Signal) -> c_int172*bb4ee6a4SAndroid Build Coastguard Worker fn from(signal: Signal) -> c_int {
173*bb4ee6a4SAndroid Build Coastguard Worker let num = signal as libc::c_int;
174*bb4ee6a4SAndroid Build Coastguard Worker if num >= Signal::Rt0 as libc::c_int {
175*bb4ee6a4SAndroid Build Coastguard Worker return num - (Signal::Rt0 as libc::c_int) + SIGRTMIN();
176*bb4ee6a4SAndroid Build Coastguard Worker }
177*bb4ee6a4SAndroid Build Coastguard Worker num
178*bb4ee6a4SAndroid Build Coastguard Worker }
179*bb4ee6a4SAndroid Build Coastguard Worker }
180*bb4ee6a4SAndroid Build Coastguard Worker
181*bb4ee6a4SAndroid Build Coastguard Worker impl TryFrom<c_int> for Signal {
182*bb4ee6a4SAndroid Build Coastguard Worker type Error = Error;
183*bb4ee6a4SAndroid Build Coastguard Worker
try_from(value: c_int) -> result::Result<Self, Self::Error>184*bb4ee6a4SAndroid Build Coastguard Worker fn try_from(value: c_int) -> result::Result<Self, Self::Error> {
185*bb4ee6a4SAndroid Build Coastguard Worker use Signal::*;
186*bb4ee6a4SAndroid Build Coastguard Worker
187*bb4ee6a4SAndroid Build Coastguard Worker Ok(match value {
188*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGABRT => Abort,
189*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGALRM => Alarm,
190*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGBUS => Bus,
191*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGCHLD => Child,
192*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGCONT => Continue,
193*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGXFSZ => ExceededFileSize,
194*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGFPE => FloatingPointException,
195*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGHUP => HangUp,
196*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGILL => IllegalInstruction,
197*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGINT => Interrupt,
198*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGIO => Io,
199*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGKILL => Kill,
200*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGPIPE => Pipe,
201*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGPWR => Power,
202*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGPROF => Profile,
203*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGQUIT => Quit,
204*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGSEGV => SegmentationViolation,
205*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGSTKFLT => StackFault,
206*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGSTOP => Stop,
207*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGSYS => Sys,
208*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGTRAP => Trap,
209*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGTERM => Terminate,
210*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGTTIN => TtyIn,
211*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGTTOU => TtyOut,
212*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGTSTP => TtyStop,
213*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGURG => Urgent,
214*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGUSR1 => User1,
215*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGUSR2 => User2,
216*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGVTALRM => VtAlarm,
217*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGWINCH => Winch,
218*bb4ee6a4SAndroid Build Coastguard Worker libc::SIGXCPU => Xcpu,
219*bb4ee6a4SAndroid Build Coastguard Worker _ => {
220*bb4ee6a4SAndroid Build Coastguard Worker if value < SIGRTMIN() {
221*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::UnrecognizedSignum(value));
222*bb4ee6a4SAndroid Build Coastguard Worker }
223*bb4ee6a4SAndroid Build Coastguard Worker let signal = match value - SIGRTMIN() {
224*bb4ee6a4SAndroid Build Coastguard Worker 0 => Rt0,
225*bb4ee6a4SAndroid Build Coastguard Worker 1 => Rt1,
226*bb4ee6a4SAndroid Build Coastguard Worker 2 => Rt2,
227*bb4ee6a4SAndroid Build Coastguard Worker 3 => Rt3,
228*bb4ee6a4SAndroid Build Coastguard Worker 4 => Rt4,
229*bb4ee6a4SAndroid Build Coastguard Worker 5 => Rt5,
230*bb4ee6a4SAndroid Build Coastguard Worker 6 => Rt6,
231*bb4ee6a4SAndroid Build Coastguard Worker 7 => Rt7,
232*bb4ee6a4SAndroid Build Coastguard Worker 8 => Rt8,
233*bb4ee6a4SAndroid Build Coastguard Worker 9 => Rt9,
234*bb4ee6a4SAndroid Build Coastguard Worker 10 => Rt10,
235*bb4ee6a4SAndroid Build Coastguard Worker 11 => Rt11,
236*bb4ee6a4SAndroid Build Coastguard Worker 12 => Rt12,
237*bb4ee6a4SAndroid Build Coastguard Worker 13 => Rt13,
238*bb4ee6a4SAndroid Build Coastguard Worker 14 => Rt14,
239*bb4ee6a4SAndroid Build Coastguard Worker 15 => Rt15,
240*bb4ee6a4SAndroid Build Coastguard Worker 16 => Rt16,
241*bb4ee6a4SAndroid Build Coastguard Worker 17 => Rt17,
242*bb4ee6a4SAndroid Build Coastguard Worker 18 => Rt18,
243*bb4ee6a4SAndroid Build Coastguard Worker 19 => Rt19,
244*bb4ee6a4SAndroid Build Coastguard Worker 20 => Rt20,
245*bb4ee6a4SAndroid Build Coastguard Worker 21 => Rt21,
246*bb4ee6a4SAndroid Build Coastguard Worker 22 => Rt22,
247*bb4ee6a4SAndroid Build Coastguard Worker 23 => Rt23,
248*bb4ee6a4SAndroid Build Coastguard Worker 24 => Rt24,
249*bb4ee6a4SAndroid Build Coastguard Worker 25 => Rt25,
250*bb4ee6a4SAndroid Build Coastguard Worker 26 => Rt26,
251*bb4ee6a4SAndroid Build Coastguard Worker 27 => Rt27,
252*bb4ee6a4SAndroid Build Coastguard Worker 28 => Rt28,
253*bb4ee6a4SAndroid Build Coastguard Worker 29 => Rt29,
254*bb4ee6a4SAndroid Build Coastguard Worker 30 => Rt30,
255*bb4ee6a4SAndroid Build Coastguard Worker 31 => Rt31,
256*bb4ee6a4SAndroid Build Coastguard Worker _ => {
257*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::UnrecognizedSignum(value));
258*bb4ee6a4SAndroid Build Coastguard Worker }
259*bb4ee6a4SAndroid Build Coastguard Worker };
260*bb4ee6a4SAndroid Build Coastguard Worker if value > SIGRTMAX() {
261*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::RtSignumGreaterThanMax(signal));
262*bb4ee6a4SAndroid Build Coastguard Worker }
263*bb4ee6a4SAndroid Build Coastguard Worker signal
264*bb4ee6a4SAndroid Build Coastguard Worker }
265*bb4ee6a4SAndroid Build Coastguard Worker })
266*bb4ee6a4SAndroid Build Coastguard Worker }
267*bb4ee6a4SAndroid Build Coastguard Worker }
268*bb4ee6a4SAndroid Build Coastguard Worker
269*bb4ee6a4SAndroid Build Coastguard Worker pub type SignalResult<T> = result::Result<T, Error>;
270*bb4ee6a4SAndroid Build Coastguard Worker
271*bb4ee6a4SAndroid Build Coastguard Worker #[link(name = "c")]
272*bb4ee6a4SAndroid Build Coastguard Worker extern "C" {
__libc_current_sigrtmin() -> c_int273*bb4ee6a4SAndroid Build Coastguard Worker fn __libc_current_sigrtmin() -> c_int;
__libc_current_sigrtmax() -> c_int274*bb4ee6a4SAndroid Build Coastguard Worker fn __libc_current_sigrtmax() -> c_int;
275*bb4ee6a4SAndroid Build Coastguard Worker }
276*bb4ee6a4SAndroid Build Coastguard Worker
277*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the minimum (inclusive) real-time signal number.
278*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_snake_case)]
SIGRTMIN() -> c_int279*bb4ee6a4SAndroid Build Coastguard Worker pub fn SIGRTMIN() -> c_int {
280*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: trivially safe
281*bb4ee6a4SAndroid Build Coastguard Worker unsafe { __libc_current_sigrtmin() }
282*bb4ee6a4SAndroid Build Coastguard Worker }
283*bb4ee6a4SAndroid Build Coastguard Worker
284*bb4ee6a4SAndroid Build Coastguard Worker /// Returns the maximum (inclusive) real-time signal number.
285*bb4ee6a4SAndroid Build Coastguard Worker #[allow(non_snake_case)]
SIGRTMAX() -> c_int286*bb4ee6a4SAndroid Build Coastguard Worker pub fn SIGRTMAX() -> c_int {
287*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: trivially safe
288*bb4ee6a4SAndroid Build Coastguard Worker unsafe { __libc_current_sigrtmax() }
289*bb4ee6a4SAndroid Build Coastguard Worker }
290*bb4ee6a4SAndroid Build Coastguard Worker
valid_rt_signal_num(num: c_int) -> bool291*bb4ee6a4SAndroid Build Coastguard Worker fn valid_rt_signal_num(num: c_int) -> bool {
292*bb4ee6a4SAndroid Build Coastguard Worker num >= SIGRTMIN() && num <= SIGRTMAX()
293*bb4ee6a4SAndroid Build Coastguard Worker }
294*bb4ee6a4SAndroid Build Coastguard Worker
295*bb4ee6a4SAndroid Build Coastguard Worker /// Registers `handler` as the signal handler of signum `num`.
296*bb4ee6a4SAndroid Build Coastguard Worker ///
297*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
298*bb4ee6a4SAndroid Build Coastguard Worker ///
299*bb4ee6a4SAndroid Build Coastguard Worker /// This is considered unsafe because the given handler will be called asynchronously, interrupting
300*bb4ee6a4SAndroid Build Coastguard Worker /// whatever the thread was doing and therefore must only do async-signal-safe operations.
register_signal_handler(num: c_int, handler: extern "C" fn(c_int)) -> Result<()>301*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe fn register_signal_handler(num: c_int, handler: extern "C" fn(c_int)) -> Result<()> {
302*bb4ee6a4SAndroid Build Coastguard Worker let mut sigact: sigaction = mem::zeroed();
303*bb4ee6a4SAndroid Build Coastguard Worker sigact.sa_flags = SA_RESTART;
304*bb4ee6a4SAndroid Build Coastguard Worker sigact.sa_sigaction = handler as *const () as usize;
305*bb4ee6a4SAndroid Build Coastguard Worker
306*bb4ee6a4SAndroid Build Coastguard Worker let ret = sigaction(num, &sigact, null_mut());
307*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
308*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
309*bb4ee6a4SAndroid Build Coastguard Worker }
310*bb4ee6a4SAndroid Build Coastguard Worker
311*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
312*bb4ee6a4SAndroid Build Coastguard Worker }
313*bb4ee6a4SAndroid Build Coastguard Worker
314*bb4ee6a4SAndroid Build Coastguard Worker /// Resets the signal handler of signum `num` back to the default.
clear_signal_handler(num: c_int) -> Result<()>315*bb4ee6a4SAndroid Build Coastguard Worker pub fn clear_signal_handler(num: c_int) -> Result<()> {
316*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
317*bb4ee6a4SAndroid Build Coastguard Worker // Safe because sigaction is owned and expected to be initialized ot zeros.
318*bb4ee6a4SAndroid Build Coastguard Worker let mut sigact: sigaction = unsafe { mem::zeroed() };
319*bb4ee6a4SAndroid Build Coastguard Worker sigact.sa_flags = SA_RESTART;
320*bb4ee6a4SAndroid Build Coastguard Worker sigact.sa_sigaction = SIG_DFL;
321*bb4ee6a4SAndroid Build Coastguard Worker
322*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
323*bb4ee6a4SAndroid Build Coastguard Worker // Safe because sigact is owned, and this is restoring the default signal handler.
324*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { sigaction(num, &sigact, null_mut()) };
325*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
326*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
327*bb4ee6a4SAndroid Build Coastguard Worker }
328*bb4ee6a4SAndroid Build Coastguard Worker
329*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
330*bb4ee6a4SAndroid Build Coastguard Worker }
331*bb4ee6a4SAndroid Build Coastguard Worker
332*bb4ee6a4SAndroid Build Coastguard Worker /// Registers `handler` as the signal handler for the real-time signal with signum `num`.
333*bb4ee6a4SAndroid Build Coastguard Worker ///
334*bb4ee6a4SAndroid Build Coastguard Worker /// The value of `num` must be within [`SIGRTMIN`, `SIGRTMAX`] range.
335*bb4ee6a4SAndroid Build Coastguard Worker ///
336*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
337*bb4ee6a4SAndroid Build Coastguard Worker ///
338*bb4ee6a4SAndroid Build Coastguard Worker /// This is considered unsafe because the given handler will be called asynchronously, interrupting
339*bb4ee6a4SAndroid Build Coastguard Worker /// whatever the thread was doing and therefore must only do async-signal-safe operations.
register_rt_signal_handler(num: c_int, handler: extern "C" fn(c_int)) -> Result<()>340*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe fn register_rt_signal_handler(num: c_int, handler: extern "C" fn(c_int)) -> Result<()> {
341*bb4ee6a4SAndroid Build Coastguard Worker if !valid_rt_signal_num(num) {
342*bb4ee6a4SAndroid Build Coastguard Worker return Err(ErrnoError::new(EINVAL));
343*bb4ee6a4SAndroid Build Coastguard Worker }
344*bb4ee6a4SAndroid Build Coastguard Worker
345*bb4ee6a4SAndroid Build Coastguard Worker register_signal_handler(num, handler)
346*bb4ee6a4SAndroid Build Coastguard Worker }
347*bb4ee6a4SAndroid Build Coastguard Worker
348*bb4ee6a4SAndroid Build Coastguard Worker /// Creates `sigset` from an array of signal numbers.
349*bb4ee6a4SAndroid Build Coastguard Worker ///
350*bb4ee6a4SAndroid Build Coastguard Worker /// This is a helper function used when we want to manipulate signals.
create_sigset(signals: &[c_int]) -> Result<sigset_t>351*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_sigset(signals: &[c_int]) -> Result<sigset_t> {
352*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
353*bb4ee6a4SAndroid Build Coastguard Worker // sigset will actually be initialized by sigemptyset below.
354*bb4ee6a4SAndroid Build Coastguard Worker let mut sigset: sigset_t = unsafe { mem::zeroed() };
355*bb4ee6a4SAndroid Build Coastguard Worker
356*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
357*bb4ee6a4SAndroid Build Coastguard Worker // Safe - return value is checked.
358*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { sigemptyset(&mut sigset) };
359*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
360*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
361*bb4ee6a4SAndroid Build Coastguard Worker }
362*bb4ee6a4SAndroid Build Coastguard Worker
363*bb4ee6a4SAndroid Build Coastguard Worker for signal in signals {
364*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
365*bb4ee6a4SAndroid Build Coastguard Worker // Safe - return value is checked.
366*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { sigaddset(&mut sigset, *signal) };
367*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
368*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
369*bb4ee6a4SAndroid Build Coastguard Worker }
370*bb4ee6a4SAndroid Build Coastguard Worker }
371*bb4ee6a4SAndroid Build Coastguard Worker
372*bb4ee6a4SAndroid Build Coastguard Worker Ok(sigset)
373*bb4ee6a4SAndroid Build Coastguard Worker }
374*bb4ee6a4SAndroid Build Coastguard Worker
375*bb4ee6a4SAndroid Build Coastguard Worker /// Wait for signal before continuing. The signal number of the consumed signal is returned on
376*bb4ee6a4SAndroid Build Coastguard Worker /// success. EAGAIN means the timeout was reached.
wait_for_signal(signals: &[c_int], timeout: Option<Duration>) -> Result<c_int>377*bb4ee6a4SAndroid Build Coastguard Worker pub fn wait_for_signal(signals: &[c_int], timeout: Option<Duration>) -> Result<c_int> {
378*bb4ee6a4SAndroid Build Coastguard Worker let sigset = create_sigset(signals)?;
379*bb4ee6a4SAndroid Build Coastguard Worker
380*bb4ee6a4SAndroid Build Coastguard Worker match timeout {
381*bb4ee6a4SAndroid Build Coastguard Worker Some(timeout) => {
382*bb4ee6a4SAndroid Build Coastguard Worker let ts = duration_to_timespec(timeout);
383*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
384*bb4ee6a4SAndroid Build Coastguard Worker // Safe - return value is checked.
385*bb4ee6a4SAndroid Build Coastguard Worker let ret = handle_eintr_errno!(unsafe { sigtimedwait(&sigset, null_mut(), &ts) });
386*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
387*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
388*bb4ee6a4SAndroid Build Coastguard Worker } else {
389*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret)
390*bb4ee6a4SAndroid Build Coastguard Worker }
391*bb4ee6a4SAndroid Build Coastguard Worker }
392*bb4ee6a4SAndroid Build Coastguard Worker None => {
393*bb4ee6a4SAndroid Build Coastguard Worker let mut ret: c_int = 0;
394*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: Safe because args are valid and the return value is checked.
395*bb4ee6a4SAndroid Build Coastguard Worker let err = handle_eintr_rc!(unsafe { sigwait(&sigset, &mut ret as *mut c_int) });
396*bb4ee6a4SAndroid Build Coastguard Worker if err != 0 {
397*bb4ee6a4SAndroid Build Coastguard Worker Err(ErrnoError::new(err))
398*bb4ee6a4SAndroid Build Coastguard Worker } else {
399*bb4ee6a4SAndroid Build Coastguard Worker Ok(ret)
400*bb4ee6a4SAndroid Build Coastguard Worker }
401*bb4ee6a4SAndroid Build Coastguard Worker }
402*bb4ee6a4SAndroid Build Coastguard Worker }
403*bb4ee6a4SAndroid Build Coastguard Worker }
404*bb4ee6a4SAndroid Build Coastguard Worker
405*bb4ee6a4SAndroid Build Coastguard Worker /// Retrieves the signal mask of the current thread as a vector of c_ints.
get_blocked_signals() -> SignalResult<Vec<c_int>>406*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_blocked_signals() -> SignalResult<Vec<c_int>> {
407*bb4ee6a4SAndroid Build Coastguard Worker let mut mask = Vec::new();
408*bb4ee6a4SAndroid Build Coastguard Worker
409*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
410*bb4ee6a4SAndroid Build Coastguard Worker // Safe - return values are checked.
411*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
412*bb4ee6a4SAndroid Build Coastguard Worker let mut old_sigset: sigset_t = mem::zeroed();
413*bb4ee6a4SAndroid Build Coastguard Worker let ret = pthread_sigmask(SIG_BLOCK, null(), &mut old_sigset as *mut sigset_t);
414*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
415*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::RetrieveSignalMask(ret));
416*bb4ee6a4SAndroid Build Coastguard Worker }
417*bb4ee6a4SAndroid Build Coastguard Worker
418*bb4ee6a4SAndroid Build Coastguard Worker for num in 0..=SIGRTMAX() {
419*bb4ee6a4SAndroid Build Coastguard Worker if sigismember(&old_sigset, num) > 0 {
420*bb4ee6a4SAndroid Build Coastguard Worker mask.push(num);
421*bb4ee6a4SAndroid Build Coastguard Worker }
422*bb4ee6a4SAndroid Build Coastguard Worker }
423*bb4ee6a4SAndroid Build Coastguard Worker }
424*bb4ee6a4SAndroid Build Coastguard Worker
425*bb4ee6a4SAndroid Build Coastguard Worker Ok(mask)
426*bb4ee6a4SAndroid Build Coastguard Worker }
427*bb4ee6a4SAndroid Build Coastguard Worker
428*bb4ee6a4SAndroid Build Coastguard Worker /// Masks given signal.
429*bb4ee6a4SAndroid Build Coastguard Worker ///
430*bb4ee6a4SAndroid Build Coastguard Worker /// If signal is already blocked the call will fail with Error::SignalAlreadyBlocked
431*bb4ee6a4SAndroid Build Coastguard Worker /// result.
block_signal(num: c_int) -> SignalResult<()>432*bb4ee6a4SAndroid Build Coastguard Worker pub fn block_signal(num: c_int) -> SignalResult<()> {
433*bb4ee6a4SAndroid Build Coastguard Worker let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;
434*bb4ee6a4SAndroid Build Coastguard Worker
435*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
436*bb4ee6a4SAndroid Build Coastguard Worker // Safe - return values are checked.
437*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
438*bb4ee6a4SAndroid Build Coastguard Worker let mut old_sigset: sigset_t = mem::zeroed();
439*bb4ee6a4SAndroid Build Coastguard Worker let ret = pthread_sigmask(SIG_BLOCK, &sigset, &mut old_sigset as *mut sigset_t);
440*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
441*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::BlockSignal(ErrnoError::last()));
442*bb4ee6a4SAndroid Build Coastguard Worker }
443*bb4ee6a4SAndroid Build Coastguard Worker let ret = sigismember(&old_sigset, num);
444*bb4ee6a4SAndroid Build Coastguard Worker match ret.cmp(&0) {
445*bb4ee6a4SAndroid Build Coastguard Worker Ordering::Less => {
446*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::CompareBlockedSignals(ErrnoError::last()));
447*bb4ee6a4SAndroid Build Coastguard Worker }
448*bb4ee6a4SAndroid Build Coastguard Worker Ordering::Greater => {
449*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::SignalAlreadyBlocked(num));
450*bb4ee6a4SAndroid Build Coastguard Worker }
451*bb4ee6a4SAndroid Build Coastguard Worker _ => (),
452*bb4ee6a4SAndroid Build Coastguard Worker };
453*bb4ee6a4SAndroid Build Coastguard Worker }
454*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
455*bb4ee6a4SAndroid Build Coastguard Worker }
456*bb4ee6a4SAndroid Build Coastguard Worker
457*bb4ee6a4SAndroid Build Coastguard Worker /// Unmasks given signal.
unblock_signal(num: c_int) -> SignalResult<()>458*bb4ee6a4SAndroid Build Coastguard Worker pub fn unblock_signal(num: c_int) -> SignalResult<()> {
459*bb4ee6a4SAndroid Build Coastguard Worker let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;
460*bb4ee6a4SAndroid Build Coastguard Worker
461*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
462*bb4ee6a4SAndroid Build Coastguard Worker // Safe - return value is checked.
463*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { pthread_sigmask(SIG_UNBLOCK, &sigset, null_mut()) };
464*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
465*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::UnblockSignal(ErrnoError::last()));
466*bb4ee6a4SAndroid Build Coastguard Worker }
467*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
468*bb4ee6a4SAndroid Build Coastguard Worker }
469*bb4ee6a4SAndroid Build Coastguard Worker
470*bb4ee6a4SAndroid Build Coastguard Worker /// Clears pending signal.
clear_signal(num: c_int) -> SignalResult<()>471*bb4ee6a4SAndroid Build Coastguard Worker pub fn clear_signal(num: c_int) -> SignalResult<()> {
472*bb4ee6a4SAndroid Build Coastguard Worker let sigset = create_sigset(&[num]).map_err(Error::CreateSigset)?;
473*bb4ee6a4SAndroid Build Coastguard Worker
474*bb4ee6a4SAndroid Build Coastguard Worker while {
475*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
476*bb4ee6a4SAndroid Build Coastguard Worker // This is safe as we are rigorously checking return values
477*bb4ee6a4SAndroid Build Coastguard Worker // of libc calls.
478*bb4ee6a4SAndroid Build Coastguard Worker unsafe {
479*bb4ee6a4SAndroid Build Coastguard Worker let mut siginfo: siginfo_t = mem::zeroed();
480*bb4ee6a4SAndroid Build Coastguard Worker let ts = timespec {
481*bb4ee6a4SAndroid Build Coastguard Worker tv_sec: 0,
482*bb4ee6a4SAndroid Build Coastguard Worker tv_nsec: 0,
483*bb4ee6a4SAndroid Build Coastguard Worker };
484*bb4ee6a4SAndroid Build Coastguard Worker // Attempt to consume one instance of pending signal. If signal
485*bb4ee6a4SAndroid Build Coastguard Worker // is not pending, the call will fail with EAGAIN or EINTR.
486*bb4ee6a4SAndroid Build Coastguard Worker let ret = sigtimedwait(&sigset, &mut siginfo, &ts);
487*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
488*bb4ee6a4SAndroid Build Coastguard Worker let e = ErrnoError::last();
489*bb4ee6a4SAndroid Build Coastguard Worker match e.errno() {
490*bb4ee6a4SAndroid Build Coastguard Worker EAGAIN | EINTR => {}
491*bb4ee6a4SAndroid Build Coastguard Worker _ => {
492*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::ClearWaitPending(ErrnoError::last()));
493*bb4ee6a4SAndroid Build Coastguard Worker }
494*bb4ee6a4SAndroid Build Coastguard Worker }
495*bb4ee6a4SAndroid Build Coastguard Worker }
496*bb4ee6a4SAndroid Build Coastguard Worker
497*bb4ee6a4SAndroid Build Coastguard Worker // This sigset will be actually filled with `sigpending` call.
498*bb4ee6a4SAndroid Build Coastguard Worker let mut chkset: sigset_t = mem::zeroed();
499*bb4ee6a4SAndroid Build Coastguard Worker // See if more instances of the signal are pending.
500*bb4ee6a4SAndroid Build Coastguard Worker let ret = sigpending(&mut chkset);
501*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
502*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::ClearGetPending(ErrnoError::last()));
503*bb4ee6a4SAndroid Build Coastguard Worker }
504*bb4ee6a4SAndroid Build Coastguard Worker
505*bb4ee6a4SAndroid Build Coastguard Worker let ret = sigismember(&chkset, num);
506*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
507*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::ClearCheckPending(ErrnoError::last()));
508*bb4ee6a4SAndroid Build Coastguard Worker }
509*bb4ee6a4SAndroid Build Coastguard Worker
510*bb4ee6a4SAndroid Build Coastguard Worker // This is do-while loop condition.
511*bb4ee6a4SAndroid Build Coastguard Worker ret != 0
512*bb4ee6a4SAndroid Build Coastguard Worker }
513*bb4ee6a4SAndroid Build Coastguard Worker } {}
514*bb4ee6a4SAndroid Build Coastguard Worker
515*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
516*bb4ee6a4SAndroid Build Coastguard Worker }
517*bb4ee6a4SAndroid Build Coastguard Worker
518*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
519*bb4ee6a4SAndroid Build Coastguard Worker /// This is marked unsafe because it allows signals to be sent to arbitrary PIDs. Sending some
520*bb4ee6a4SAndroid Build Coastguard Worker /// signals may lead to undefined behavior. Also, the return codes of the child processes need to be
521*bb4ee6a4SAndroid Build Coastguard Worker /// reaped to avoid leaking zombie processes.
kill(pid: Pid, signum: c_int) -> Result<()>522*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe fn kill(pid: Pid, signum: c_int) -> Result<()> {
523*bb4ee6a4SAndroid Build Coastguard Worker let ret = libc::kill(pid, signum);
524*bb4ee6a4SAndroid Build Coastguard Worker
525*bb4ee6a4SAndroid Build Coastguard Worker if ret != 0 {
526*bb4ee6a4SAndroid Build Coastguard Worker errno_result()
527*bb4ee6a4SAndroid Build Coastguard Worker } else {
528*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
529*bb4ee6a4SAndroid Build Coastguard Worker }
530*bb4ee6a4SAndroid Build Coastguard Worker }
531*bb4ee6a4SAndroid Build Coastguard Worker
532*bb4ee6a4SAndroid Build Coastguard Worker /// Trait for threads that can be signalled via `pthread_kill`.
533*bb4ee6a4SAndroid Build Coastguard Worker ///
534*bb4ee6a4SAndroid Build Coastguard Worker /// Note that this is only useful for signals between SIGRTMIN and SIGRTMAX because these are
535*bb4ee6a4SAndroid Build Coastguard Worker /// guaranteed to not be used by the C runtime.
536*bb4ee6a4SAndroid Build Coastguard Worker ///
537*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety
538*bb4ee6a4SAndroid Build Coastguard Worker /// This is marked unsafe because the implementation of this trait must guarantee that the returned
539*bb4ee6a4SAndroid Build Coastguard Worker /// pthread_t is valid and has a lifetime at least that of the trait object.
540*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe trait Killable {
pthread_handle(&self) -> pthread_t541*bb4ee6a4SAndroid Build Coastguard Worker fn pthread_handle(&self) -> pthread_t;
542*bb4ee6a4SAndroid Build Coastguard Worker
543*bb4ee6a4SAndroid Build Coastguard Worker /// Sends the signal `num` to this killable thread.
544*bb4ee6a4SAndroid Build Coastguard Worker ///
545*bb4ee6a4SAndroid Build Coastguard Worker /// The value of `num` must be within [`SIGRTMIN`, `SIGRTMAX`] range.
kill(&self, num: c_int) -> Result<()>546*bb4ee6a4SAndroid Build Coastguard Worker fn kill(&self, num: c_int) -> Result<()> {
547*bb4ee6a4SAndroid Build Coastguard Worker if !valid_rt_signal_num(num) {
548*bb4ee6a4SAndroid Build Coastguard Worker return Err(ErrnoError::new(EINVAL));
549*bb4ee6a4SAndroid Build Coastguard Worker }
550*bb4ee6a4SAndroid Build Coastguard Worker
551*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
552*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we ensure we are using a valid pthread handle, a valid signal number, and
553*bb4ee6a4SAndroid Build Coastguard Worker // check the return result.
554*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { pthread_kill(self.pthread_handle(), num) };
555*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 {
556*bb4ee6a4SAndroid Build Coastguard Worker return errno_result();
557*bb4ee6a4SAndroid Build Coastguard Worker }
558*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
559*bb4ee6a4SAndroid Build Coastguard Worker }
560*bb4ee6a4SAndroid Build Coastguard Worker }
561*bb4ee6a4SAndroid Build Coastguard Worker
562*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY:
563*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we fulfill our contract of returning a genuine pthread handle.
564*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl<T> Killable for JoinHandle<T> {
pthread_handle(&self) -> pthread_t565*bb4ee6a4SAndroid Build Coastguard Worker fn pthread_handle(&self) -> pthread_t {
566*bb4ee6a4SAndroid Build Coastguard Worker self.as_pthread_t() as _
567*bb4ee6a4SAndroid Build Coastguard Worker }
568*bb4ee6a4SAndroid Build Coastguard Worker }
569*bb4ee6a4SAndroid Build Coastguard Worker
570*bb4ee6a4SAndroid Build Coastguard Worker // Represents a temporarily blocked signal. It will unblock the signal when dropped.
571*bb4ee6a4SAndroid Build Coastguard Worker pub struct BlockedSignal {
572*bb4ee6a4SAndroid Build Coastguard Worker signal_num: c_int,
573*bb4ee6a4SAndroid Build Coastguard Worker }
574*bb4ee6a4SAndroid Build Coastguard Worker
575*bb4ee6a4SAndroid Build Coastguard Worker impl BlockedSignal {
576*bb4ee6a4SAndroid Build Coastguard Worker // Returns a `BlockedSignal` if the specified signal can be blocked, otherwise None.
new(signal_num: c_int) -> Option<BlockedSignal>577*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(signal_num: c_int) -> Option<BlockedSignal> {
578*bb4ee6a4SAndroid Build Coastguard Worker if block_signal(signal_num).is_ok() {
579*bb4ee6a4SAndroid Build Coastguard Worker Some(BlockedSignal { signal_num })
580*bb4ee6a4SAndroid Build Coastguard Worker } else {
581*bb4ee6a4SAndroid Build Coastguard Worker None
582*bb4ee6a4SAndroid Build Coastguard Worker }
583*bb4ee6a4SAndroid Build Coastguard Worker }
584*bb4ee6a4SAndroid Build Coastguard Worker }
585*bb4ee6a4SAndroid Build Coastguard Worker
586*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for BlockedSignal {
drop(&mut self)587*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) {
588*bb4ee6a4SAndroid Build Coastguard Worker unblock_signal(self.signal_num).expect("failed to restore signal mask");
589*bb4ee6a4SAndroid Build Coastguard Worker }
590*bb4ee6a4SAndroid Build Coastguard Worker }
591