xref: /aosp_15_r20/external/crosvm/base/src/sys/linux/signal.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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