1use bytemuck::TransparentWrapper;
2use linux_syscall::Result as LinuxSyscallResult;
3use linux_syscall::syscall;
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5use shadow_pod::Pod;
6use vasi::VirtualAddressSpaceIndependent;
7
8use crate::bindings::{self, linux_sigval};
9use crate::const_conversions;
10use crate::const_conversions::i32_from_u32_allowing_wraparound;
11use crate::errno::Errno;
12use crate::posix_types::Pid;
13use crate::posix_types::kernel_pid_t;
14
15#[derive(Debug, Copy, Clone, Eq, PartialEq)]
18#[repr(transparent)]
19pub struct Signal(i32);
20
21#[derive(Debug, Copy, Clone)]
22pub struct SignalFromI32Error(pub i32);
23
24impl TryFrom<i32> for Signal {
25 type Error = SignalFromI32Error;
26
27 fn try_from(value: i32) -> Result<Self, Self::Error> {
28 if (1..=i32::from(Signal::SIGRT_MAX)).contains(&value) {
29 Ok(Self(value))
30 } else {
31 Err(SignalFromI32Error(value))
32 }
33 }
34}
35
36impl From<Signal> for i32 {
37 fn from(value: Signal) -> Self {
38 value.as_i32()
39 }
40}
41
42impl Signal {
43 pub const SIGHUP: Self = Self::std_from_u32_const(bindings::LINUX_SIGHUP);
44 pub const SIGINT: Self = Self::std_from_u32_const(bindings::LINUX_SIGINT);
45 pub const SIGQUIT: Self = Self::std_from_u32_const(bindings::LINUX_SIGQUIT);
46 pub const SIGILL: Self = Self::std_from_u32_const(bindings::LINUX_SIGILL);
47 pub const SIGTRAP: Self = Self::std_from_u32_const(bindings::LINUX_SIGTRAP);
48 pub const SIGABRT: Self = Self::std_from_u32_const(bindings::LINUX_SIGABRT);
49 pub const SIGBUS: Self = Self::std_from_u32_const(bindings::LINUX_SIGBUS);
50 pub const SIGFPE: Self = Self::std_from_u32_const(bindings::LINUX_SIGFPE);
51 pub const SIGKILL: Self = Self::std_from_u32_const(bindings::LINUX_SIGKILL);
52 pub const SIGUSR1: Self = Self::std_from_u32_const(bindings::LINUX_SIGUSR1);
53 pub const SIGSEGV: Self = Self::std_from_u32_const(bindings::LINUX_SIGSEGV);
54 pub const SIGUSR2: Self = Self::std_from_u32_const(bindings::LINUX_SIGUSR2);
55 pub const SIGPIPE: Self = Self::std_from_u32_const(bindings::LINUX_SIGPIPE);
56 pub const SIGALRM: Self = Self::std_from_u32_const(bindings::LINUX_SIGALRM);
57 pub const SIGTERM: Self = Self::std_from_u32_const(bindings::LINUX_SIGTERM);
58 pub const SIGSTKFLT: Self = Self::std_from_u32_const(bindings::LINUX_SIGSTKFLT);
59 pub const SIGCHLD: Self = Self::std_from_u32_const(bindings::LINUX_SIGCHLD);
60 pub const SIGCONT: Self = Self::std_from_u32_const(bindings::LINUX_SIGCONT);
61 pub const SIGSTOP: Self = Self::std_from_u32_const(bindings::LINUX_SIGSTOP);
62 pub const SIGTSTP: Self = Self::std_from_u32_const(bindings::LINUX_SIGTSTP);
63 pub const SIGTTIN: Self = Self::std_from_u32_const(bindings::LINUX_SIGTTIN);
64 pub const SIGTTOU: Self = Self::std_from_u32_const(bindings::LINUX_SIGTTOU);
65 pub const SIGURG: Self = Self::std_from_u32_const(bindings::LINUX_SIGURG);
66 pub const SIGXCPU: Self = Self::std_from_u32_const(bindings::LINUX_SIGXCPU);
67 pub const SIGXFSZ: Self = Self::std_from_u32_const(bindings::LINUX_SIGXFSZ);
68 pub const SIGVTALRM: Self = Self::std_from_u32_const(bindings::LINUX_SIGVTALRM);
69 pub const SIGPROF: Self = Self::std_from_u32_const(bindings::LINUX_SIGPROF);
70 pub const SIGWINCH: Self = Self::std_from_u32_const(bindings::LINUX_SIGWINCH);
71 pub const SIGIO: Self = Self::std_from_u32_const(bindings::LINUX_SIGIO);
72 pub const SIGPWR: Self = Self::std_from_u32_const(bindings::LINUX_SIGPWR);
73 pub const SIGSYS: Self = Self::std_from_u32_const(bindings::LINUX_SIGSYS);
74
75 pub const STANDARD_MAX: Self = Self(31);
76
77 pub const SIGRT_MIN: Self = Self::rt_from_u32_const(bindings::LINUX_SIGRTMIN);
78 pub const SIGRT_MAX: Self = Self::rt_from_u32_const(64);
80
81 pub const MIN: Self = Self(1);
82 pub const MAX: Self = Self::SIGRT_MAX;
83
84 pub const SIGIOT: Self = Self::std_from_u32_const(bindings::LINUX_SIGIOT);
86 pub const SIGPOLL: Self = Self::std_from_u32_const(bindings::LINUX_SIGPOLL);
87 pub const SIGUNUSED: Self = Self::std_from_u32_const(bindings::LINUX_SIGUNUSED);
88
89 pub fn is_realtime(&self) -> bool {
90 (i32::from(Self::SIGRT_MIN)..=i32::from(Self::SIGRT_MAX)).contains(&self.0)
91 }
92
93 pub const fn as_i32(&self) -> i32 {
94 self.0
95 }
96
97 pub fn standard_signals() -> impl Iterator<Item = Signal> {
98 (i32::from(Self::MIN)..=i32::from(Self::STANDARD_MAX)).map(|i| Self::try_from(i).unwrap())
99 }
100
101 const fn std_from_u32_const(val: u32) -> Self {
103 let rv = Self(const_conversions::i32_from_u32(val));
104 assert!(rv.0 as u32 == val);
105 assert!(rv.0 <= Self::STANDARD_MAX.0);
106 rv
107 }
108
109 const fn rt_from_u32_const(val: u32) -> Self {
110 let rv = Self(const_conversions::i32_from_u32(val));
111 assert!(rv.0 as u32 == val);
112 assert!(rv.0 > Self::STANDARD_MAX.0);
113 rv
114 }
115
116 pub fn as_raw(this: Option<Self>) -> i32 {
118 this.map(|s| s.as_i32()).unwrap_or(0)
119 }
120}
121
122bitflags::bitflags! {
123 #[repr(transparent)]
124 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
125 pub struct SigActionFlags: u64 {
126 const SA_NOCLDSTOP = const_conversions::u64_from_u32(bindings::LINUX_SA_NOCLDSTOP);
127 const SA_NOCLDWAIT = const_conversions::u64_from_u32(bindings::LINUX_SA_NOCLDWAIT);
128 const SA_NODEFER = const_conversions::u64_from_u32(bindings::LINUX_SA_NODEFER);
129 const SA_ONSTACK = const_conversions::u64_from_u32(bindings::LINUX_SA_ONSTACK);
130 const SA_RESETHAND = const_conversions::u64_from_u32(bindings::LINUX_SA_RESETHAND);
131 const SA_RESTART = const_conversions::u64_from_u32(bindings::LINUX_SA_RESTART);
132 const SA_RESTORER = const_conversions::u64_from_u32(bindings::LINUX_SA_RESTORER);
133 const SA_SIGINFO = const_conversions::u64_from_u32(bindings::LINUX_SA_SIGINFO);
134 }
135}
136unsafe impl VirtualAddressSpaceIndependent for SigActionFlags {}
138
139#[derive(Copy, Clone, Debug, Eq, PartialEq)]
141pub enum SigInfoCode {
142 Si(SigInfoCodeSi),
143 Ill(SigInfoCodeIll),
144 Fpe(SigInfoCodeFpe),
145 Segv(SigInfoCodeSegv),
146 Bus(SigInfoCodeBus),
147 Trap(SigInfoCodeTrap),
148 Cld(SigInfoCodeCld),
149 Poll(SigInfoCodePoll),
150 Sys(SigInfoCodeSys),
151}
152
153#[derive(Debug, Copy, Clone)]
154pub struct SigInfoCodeFromRawError {
155 pub code: i32,
156 pub signo: i32,
157}
158
159impl SigInfoCode {
160 fn try_from_raw(raw_code: i32, raw_signo: i32) -> Result<Self, SigInfoCodeFromRawError> {
163 if let Ok(si_code) = SigInfoCodeSi::try_from(raw_code) {
167 return Ok(SigInfoCode::Si(si_code));
168 }
169
170 let err = SigInfoCodeFromRawError {
171 code: raw_code,
172 signo: raw_signo,
173 };
174
175 let Ok(signal) = Signal::try_from(raw_signo) else {
176 return Err(err);
177 };
178
179 match signal {
181 Signal::SIGCHLD => SigInfoCodeCld::try_from(raw_code)
182 .map(SigInfoCode::Cld)
183 .or(Err(err)),
184 Signal::SIGILL => SigInfoCodeIll::try_from(raw_code)
185 .map(SigInfoCode::Ill)
186 .or(Err(err)),
187 Signal::SIGFPE => SigInfoCodeFpe::try_from(raw_code)
188 .map(SigInfoCode::Fpe)
189 .or(Err(err)),
190 Signal::SIGSEGV => SigInfoCodeSegv::try_from(raw_code)
191 .map(SigInfoCode::Segv)
192 .or(Err(err)),
193 Signal::SIGBUS => SigInfoCodeBus::try_from(raw_code)
194 .map(SigInfoCode::Bus)
195 .or(Err(err)),
196 Signal::SIGTRAP => SigInfoCodeTrap::try_from(raw_code)
197 .map(SigInfoCode::Trap)
198 .or(Err(err)),
199 Signal::SIGPOLL => SigInfoCodePoll::try_from(raw_code)
200 .map(SigInfoCode::Poll)
201 .or(Err(err)),
202 Signal::SIGSYS => SigInfoCodeSys::try_from(raw_code)
203 .map(SigInfoCode::Sys)
204 .or(Err(err)),
205 _ => Err(err),
206 }
207 }
208}
209
210#[allow(non_camel_case_types)]
211#[repr(i32)]
212#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
213pub enum SigInfoCodeSi {
214 SI_USER = const_conversions::i32_from_u32(bindings::LINUX_SI_USER),
216 SI_KERNEL = const_conversions::i32_from_u32(bindings::LINUX_SI_KERNEL),
218 SI_QUEUE = bindings::LINUX_SI_QUEUE,
220 SI_TIMER = bindings::LINUX_SI_TIMER,
222 SI_MESGQ = bindings::LINUX_SI_MESGQ,
224 SI_ASYNCIO = bindings::LINUX_SI_ASYNCIO,
226 SI_TKILL = bindings::LINUX_SI_TKILL,
228}
229
230#[allow(non_camel_case_types)]
232#[repr(i32)]
233#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
234pub enum SigInfoCodeCld {
235 CLD_EXITED = const_conversions::i32_from_u32(bindings::LINUX_CLD_EXITED),
237 CLD_KILLED = const_conversions::i32_from_u32(bindings::LINUX_CLD_KILLED),
239 CLD_DUMPED = const_conversions::i32_from_u32(bindings::LINUX_CLD_DUMPED),
241 CLD_TRAPPED = const_conversions::i32_from_u32(bindings::LINUX_CLD_TRAPPED),
243 CLD_STOPPED = const_conversions::i32_from_u32(bindings::LINUX_CLD_STOPPED),
245 CLD_CONTINUED = const_conversions::i32_from_u32(bindings::LINUX_CLD_CONTINUED),
247}
248
249#[allow(non_camel_case_types)]
251#[repr(i32)]
252#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
253pub enum SigInfoCodeIll {
254 ILL_ILLOPC = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLOPC),
255 ILL_ILLOPN = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLOPN),
256 ILL_ILLADR = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLADR),
257 ILL_ILLTRP = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLTRP),
258 ILL_PRVOPC = const_conversions::i32_from_u32(bindings::LINUX_ILL_PRVOPC),
259 ILL_PRVREG = const_conversions::i32_from_u32(bindings::LINUX_ILL_PRVREG),
260 ILL_COPROC = const_conversions::i32_from_u32(bindings::LINUX_ILL_COPROC),
261 ILL_BADSTK = const_conversions::i32_from_u32(bindings::LINUX_ILL_BADSTK),
262 ILL_BADIADDR = const_conversions::i32_from_u32(bindings::LINUX_ILL_BADIADDR),
263}
264
265#[allow(non_camel_case_types)]
267#[repr(i32)]
268#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
269pub enum SigInfoCodeFpe {
270 FPE_INTDIV = const_conversions::i32_from_u32(bindings::LINUX_FPE_INTDIV),
271 FPE_INTOVF = const_conversions::i32_from_u32(bindings::LINUX_FPE_INTOVF),
272 FPE_FLTDIV = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTDIV),
273 FPE_FLTOVF = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTOVF),
274 FPE_FLTUND = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTUND),
275 FPE_FLTRES = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTRES),
276 FPE_FLTINV = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTINV),
277 FPE_FLTSUB = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTSUB),
278 FPE_FLTUNK = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTUNK),
279 FPE_CONDTRAP = const_conversions::i32_from_u32(bindings::LINUX_FPE_CONDTRAP),
280}
281
282#[allow(non_camel_case_types)]
284#[repr(i32)]
285#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
286pub enum SigInfoCodeSegv {
287 SEGV_MAPERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_MAPERR),
288 SEGV_ACCERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ACCERR),
289 SEGV_BNDERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_BNDERR),
290 SEGV_PKUERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_PKUERR),
291 SEGV_ACCADI = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ACCADI),
292 SEGV_ADIDERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ADIDERR),
293 SEGV_ADIPERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ADIPERR),
294 SEGV_MTEAERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_MTEAERR),
295 SEGV_MTESERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_MTESERR),
296}
297
298#[allow(non_camel_case_types)]
300#[repr(i32)]
301#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
302pub enum SigInfoCodeBus {
303 BUS_ADRALN = const_conversions::i32_from_u32(bindings::LINUX_BUS_ADRALN),
304 BUS_ADRERR = const_conversions::i32_from_u32(bindings::LINUX_BUS_ADRERR),
305 BUS_OBJERR = const_conversions::i32_from_u32(bindings::LINUX_BUS_OBJERR),
306 BUS_MCEERR_AR = const_conversions::i32_from_u32(bindings::LINUX_BUS_MCEERR_AR),
307 BUS_MCEERR_AO = const_conversions::i32_from_u32(bindings::LINUX_BUS_MCEERR_AO),
308}
309
310#[allow(non_camel_case_types)]
312#[repr(i32)]
313#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
314pub enum SigInfoCodeTrap {
315 TRAP_BRKPT = const_conversions::i32_from_u32(bindings::LINUX_TRAP_BRKPT),
316 TRAP_TRACE = const_conversions::i32_from_u32(bindings::LINUX_TRAP_TRACE),
317 TRAP_BRANCH = const_conversions::i32_from_u32(bindings::LINUX_TRAP_BRANCH),
318 TRAP_HWBKPT = const_conversions::i32_from_u32(bindings::LINUX_TRAP_HWBKPT),
319 TRAP_UNK = const_conversions::i32_from_u32(bindings::LINUX_TRAP_UNK),
320 TRAP_PERF = const_conversions::i32_from_u32(bindings::LINUX_TRAP_PERF),
321}
322
323#[allow(non_camel_case_types)]
325#[repr(i32)]
326#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
327pub enum SigInfoCodePoll {
328 POLL_IN = const_conversions::i32_from_u32(bindings::LINUX_POLL_IN),
329 POLL_OUT = const_conversions::i32_from_u32(bindings::LINUX_POLL_OUT),
330 POLL_MSG = const_conversions::i32_from_u32(bindings::LINUX_POLL_MSG),
331 POLL_ERR = const_conversions::i32_from_u32(bindings::LINUX_POLL_ERR),
332 POLL_PRI = const_conversions::i32_from_u32(bindings::LINUX_POLL_PRI),
333 POLL_HUP = const_conversions::i32_from_u32(bindings::LINUX_POLL_HUP),
334}
335
336#[allow(non_camel_case_types)]
338#[repr(i32)]
339#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
340pub enum SigInfoCodeSys {
341 SYS_SECCOMP = const_conversions::i32_from_u32(bindings::LINUX_SYS_SECCOMP),
342}
343
344#[allow(non_camel_case_types)]
345pub type linux_siginfo_t = bindings::linux_siginfo_t;
346
347type SigInfoDetailsFields = bindings::linux___sifields;
348
349pub type SigInfoDetailsKill = bindings::linux___sifields__bindgen_ty_1;
368pub type SigInfoDetailsTimer = bindings::linux___sifields__bindgen_ty_2;
369pub type SigInfoDetailsRt = bindings::linux___sifields__bindgen_ty_3;
370pub type SigInfoDetailsSigChld = bindings::linux___sifields__bindgen_ty_4;
371pub type SigInfoDetailsSigFault = bindings::linux___sifields__bindgen_ty_5;
372pub type SigInfoDetailsSigPoll = bindings::linux___sifields__bindgen_ty_6;
373pub type SigInfoDetailsSigSys = bindings::linux___sifields__bindgen_ty_7;
374
375pub enum SigInfoDetails {
376 Kill(SigInfoDetailsKill),
377 Timer(SigInfoDetailsTimer),
378 Rt(SigInfoDetailsRt),
379 SigChld(SigInfoDetailsSigChld),
380 SigFault(SigInfoDetailsSigFault),
381 SigPoll(SigInfoDetailsSigPoll),
382 SigSys(SigInfoDetailsSigSys),
383}
384
385#[derive(Copy, Clone, Debug)]
404#[repr(transparent)]
405#[allow(non_camel_case_types)]
406pub struct siginfo_t(linux_siginfo_t);
407unsafe impl Send for siginfo_t {}
410unsafe impl Pod for siginfo_t {}
411
412impl siginfo_t {
413 fn inner(&self) -> &bindings::linux_siginfo__bindgen_ty_1__bindgen_ty_1 {
417 unsafe { &self.0.l__bindgen_anon_1.l__bindgen_anon_1 }
419 }
420
421 pub unsafe fn wrap_assume_initd(si: linux_siginfo_t) -> Self {
427 Self(si)
428 }
429
430 pub unsafe fn wrap_ref_assume_initd(si: &linux_siginfo_t) -> &Self {
436 unsafe { &*(core::ptr::from_ref(si) as *const Self) }
437 }
438
439 pub unsafe fn wrap_mut_assume_initd(si: &mut linux_siginfo_t) -> &mut Self {
445 unsafe { &mut *(core::ptr::from_mut(si) as *mut Self) }
446 }
447
448 pub unsafe fn peel(si: Self) -> linux_siginfo_t {
452 si.0
453 }
454
455 #[inline]
456 pub fn signal(&self) -> Result<Signal, SignalFromI32Error> {
457 Signal::try_from(self.inner().lsi_signo)
458 }
459
460 #[inline]
461 pub fn code(&self) -> Result<SigInfoCode, SigInfoCodeFromRawError> {
462 SigInfoCode::try_from_raw(self.inner().lsi_code, self.inner().lsi_signo)
463 }
464
465 pub unsafe fn details(&self) -> Option<SigInfoDetails> {
470 let Ok(code) = self.code() else {
471 return None;
472 };
473 match code {
474 SigInfoCode::Si(SigInfoCodeSi::SI_USER) => Some(SigInfoDetails::Kill(unsafe {
475 self.inner().l_sifields.l_kill
476 })),
477 SigInfoCode::Si(SigInfoCodeSi::SI_KERNEL) => Some(SigInfoDetails::SigFault(unsafe {
478 self.inner().l_sifields.l_sigfault
479 })),
480 SigInfoCode::Si(SigInfoCodeSi::SI_QUEUE) => {
481 Some(SigInfoDetails::Rt(unsafe { self.inner().l_sifields.l_rt }))
482 }
483 SigInfoCode::Si(SigInfoCodeSi::SI_TIMER) => Some(SigInfoDetails::Timer(unsafe {
484 self.inner().l_sifields.l_timer
485 })),
486 SigInfoCode::Si(SigInfoCodeSi::SI_MESGQ) => {
487 Some(SigInfoDetails::Rt(unsafe { self.inner().l_sifields.l_rt }))
488 }
489 SigInfoCode::Si(SigInfoCodeSi::SI_ASYNCIO) => Some(SigInfoDetails::SigPoll(unsafe {
490 self.inner().l_sifields.l_sigpoll
491 })),
492 SigInfoCode::Si(SigInfoCodeSi::SI_TKILL) => Some(SigInfoDetails::Kill(unsafe {
493 self.inner().l_sifields.l_kill
494 })),
495 SigInfoCode::Cld(_) => Some(SigInfoDetails::SigChld(unsafe {
496 self.inner().l_sifields.l_sigchld
497 })),
498 SigInfoCode::Ill(_) => Some(SigInfoDetails::SigFault(unsafe {
501 self.inner().l_sifields.l_sigfault
502 })),
503 SigInfoCode::Fpe(_) => Some(SigInfoDetails::SigFault(unsafe {
504 self.inner().l_sifields.l_sigfault
505 })),
506 SigInfoCode::Segv(_) => Some(SigInfoDetails::SigFault(unsafe {
507 self.inner().l_sifields.l_sigfault
508 })),
509 SigInfoCode::Bus(_) => Some(SigInfoDetails::SigFault(unsafe {
510 self.inner().l_sifields.l_sigfault
511 })),
512 SigInfoCode::Trap(_) => Some(SigInfoDetails::SigFault(unsafe {
513 self.inner().l_sifields.l_sigfault
514 })),
515 SigInfoCode::Poll(_) => Some(SigInfoDetails::SigFault(unsafe {
516 self.inner().l_sifields.l_sigfault
517 })),
518 SigInfoCode::Sys(_) => Some(SigInfoDetails::SigSys(unsafe {
519 self.inner().l_sifields.l_sigsys
520 })),
521 }
522 }
523
524 unsafe fn new(signal: Signal, errno: i32, code: i32, fields: SigInfoDetailsFields) -> Self {
526 Self(bindings::linux_siginfo_t {
527 l__bindgen_anon_1: bindings::linux_siginfo__bindgen_ty_1 {
528 l__bindgen_anon_1: bindings::linux_siginfo__bindgen_ty_1__bindgen_ty_1 {
529 lsi_signo: signal.into(),
530 lsi_errno: errno,
531 lsi_code: code,
532 l_sifields: fields,
533 },
534 },
535 })
536 }
537
538 pub fn new_for_kill(signal: Signal, sender_pid: i32, sender_uid: u32) -> Self {
540 unsafe {
546 Self::new(
547 signal,
548 0,
549 SigInfoCodeSi::SI_USER.into(),
550 SigInfoDetailsFields {
551 l_kill: SigInfoDetailsKill {
552 l_pid: sender_pid,
553 l_uid: sender_uid,
554 },
555 },
556 )
557 }
558 }
559
560 pub fn new_for_tkill(signal: Signal, sender_pid: i32, sender_uid: u32) -> Self {
562 unsafe {
563 Self::new(
564 signal,
565 0,
566 SigInfoCodeSi::SI_TKILL.into(),
567 SigInfoDetailsFields {
568 l_kill: SigInfoDetailsKill {
569 l_pid: sender_pid,
570 l_uid: sender_uid,
571 },
572 },
573 )
574 }
575 }
576
577 pub fn new_for_timer(signal: Signal, timer_id: i32, overrun: i32) -> Self {
578 unsafe {
586 Self::new(
587 signal,
588 0,
589 SigInfoCodeSi::SI_TIMER.into(),
590 SigInfoDetailsFields {
591 l_timer: SigInfoDetailsTimer {
592 l_tid: timer_id,
593 l_overrun: overrun,
594 l_sigval: core::mem::zeroed(),
595 l_sys_private: 0,
596 },
597 },
598 )
599 }
600 }
601
602 pub fn new_for_mq(
604 signal: Signal,
605 sender_pid: i32,
606 sender_uid: u32,
607 sigval: linux_sigval,
608 ) -> Self {
609 unsafe {
615 Self::new(
616 signal,
617 0,
618 SigInfoCodeSi::SI_MESGQ.into(),
619 SigInfoDetailsFields {
620 l_rt: SigInfoDetailsRt {
621 l_pid: sender_pid,
622 l_uid: sender_uid,
623 l_sigval: sigval,
624 },
625 },
626 )
627 }
628 }
629
630 pub fn new_for_sigchld_exited(
631 exit_signal: Signal,
632 child_pid: i32,
633 child_uid: u32,
634 child_exit_status: i32,
635 child_utime: i64,
636 child_stime: i64,
637 ) -> Self {
638 unsafe {
648 Self::new(
649 exit_signal,
650 0,
651 SigInfoCodeCld::CLD_EXITED.into(),
652 SigInfoDetailsFields {
653 l_sigchld: SigInfoDetailsSigChld {
654 l_pid: child_pid,
655 l_uid: child_uid,
656 l_status: child_exit_status,
657 l_utime: child_utime,
658 l_stime: child_stime,
659 },
660 },
661 )
662 }
663 }
664
665 fn new_for_sigchld_signaled(
676 exit_signal: Signal,
677 code: SigInfoCodeCld,
678 child_pid: i32,
679 child_uid: u32,
680 signal: Signal,
681 child_utime: i64,
682 child_stime: i64,
683 ) -> Self {
684 unsafe {
685 Self::new(
686 exit_signal,
687 0,
688 code.into(),
689 SigInfoDetailsFields {
690 l_sigchld: SigInfoDetailsSigChld {
691 l_pid: child_pid,
692 l_uid: child_uid,
693 l_status: signal.into(),
694 l_utime: child_utime,
695 l_stime: child_stime,
696 },
697 },
698 )
699 }
700 }
701
702 pub fn new_for_sigchld_killed(
703 exit_signal: Signal,
704 child_pid: i32,
705 child_uid: u32,
706 fatal_signal: Signal,
707 child_utime: i64,
708 child_stime: i64,
709 ) -> Self {
710 Self::new_for_sigchld_signaled(
711 exit_signal,
712 SigInfoCodeCld::CLD_KILLED,
713 child_pid,
714 child_uid,
715 fatal_signal,
716 child_utime,
717 child_stime,
718 )
719 }
720 pub fn new_for_sigchld_dumped(
721 exit_signal: Signal,
722 child_pid: i32,
723 child_uid: u32,
724 fatal_signal: Signal,
725 child_utime: i64,
726 child_stime: i64,
727 ) -> Self {
728 Self::new_for_sigchld_signaled(
729 exit_signal,
730 SigInfoCodeCld::CLD_DUMPED,
731 child_pid,
732 child_uid,
733 fatal_signal,
734 child_utime,
735 child_stime,
736 )
737 }
738 pub fn new_for_sigchld_trapped(
739 exit_signal: Signal,
740 child_pid: i32,
741 child_uid: u32,
742 child_utime: i64,
743 child_stime: i64,
744 ) -> Self {
745 Self::new_for_sigchld_signaled(
746 exit_signal,
747 SigInfoCodeCld::CLD_TRAPPED,
748 child_pid,
749 child_uid,
750 Signal::SIGTRAP,
751 child_utime,
752 child_stime,
753 )
754 }
755 pub fn new_for_sigchld_stopped(
756 exit_signal: Signal,
757 child_pid: i32,
758 child_uid: u32,
759 child_utime: i64,
760 child_stime: i64,
761 ) -> Self {
762 Self::new_for_sigchld_signaled(
763 exit_signal,
764 SigInfoCodeCld::CLD_STOPPED,
765 child_pid,
766 child_uid,
767 Signal::SIGSTOP,
768 child_utime,
769 child_stime,
770 )
771 }
772 pub fn new_for_sigchld_continued(
773 exit_signal: Signal,
774 child_pid: i32,
775 child_uid: u32,
776 child_utime: i64,
777 child_stime: i64,
778 ) -> Self {
779 Self::new_for_sigchld_signaled(
780 exit_signal,
781 SigInfoCodeCld::CLD_CONTINUED,
782 child_pid,
783 child_uid,
784 Signal::SIGCONT,
785 child_utime,
786 child_stime,
787 )
788 }
789
790 }
799
800impl Default for siginfo_t {
801 fn default() -> Self {
802 unsafe { core::mem::zeroed() }
803 }
804}
805
806#[allow(non_camel_case_types)]
807pub type linux_sigset_t = bindings::linux_sigset_t;
808
809#[derive(
813 Copy,
814 Clone,
815 Eq,
816 PartialEq,
817 Debug,
818 Default,
819 VirtualAddressSpaceIndependent,
820 bytemuck_derive::TransparentWrapper,
821)]
822#[repr(transparent)]
823#[allow(non_camel_case_types)]
824pub struct sigset_t(linux_sigset_t);
825unsafe impl shadow_pod::Pod for sigset_t {}
826
827impl sigset_t {
828 pub const EMPTY: Self = Self(0);
829 pub const FULL: Self = Self(!0);
830
831 pub fn has(&self, sig: Signal) -> bool {
832 (*self & sigset_t::from(sig)).0 != 0
833 }
834
835 pub fn lowest(&self) -> Option<Signal> {
836 if self.0 == 0 {
837 return None;
838 }
839 for i in i32::from(Signal::MIN)..=i32::from(Signal::MAX) {
840 let s = Signal::try_from(i).unwrap();
841 if self.has(s) {
842 return Some(s);
843 }
844 }
845 unreachable!();
846 }
847
848 pub fn is_empty(&self) -> bool {
849 *self == sigset_t::EMPTY
850 }
851
852 pub fn del(&mut self, sig: Signal) {
853 *self &= !sigset_t::from(sig);
854 }
855
856 pub fn add(&mut self, sig: Signal) {
857 *self |= sigset_t::from(sig);
858 }
859}
860
861impl From<Signal> for sigset_t {
862 #[inline]
863 fn from(value: Signal) -> Self {
864 let value = i32::from(value);
865 debug_assert!(value <= 64);
866 Self(1 << (value - 1))
867 }
868}
869
870#[test]
871fn test_from_signal() {
872 let sigset = sigset_t::from(Signal::SIGABRT);
873 assert!(sigset.has(Signal::SIGABRT));
874 assert!(!sigset.has(Signal::SIGSEGV));
875 assert_ne!(sigset, sigset_t::EMPTY);
876}
877
878impl core::ops::BitOr for sigset_t {
879 type Output = Self;
880
881 fn bitor(self, rhs: Self) -> Self::Output {
882 Self(self.0 | rhs.0)
883 }
884}
885
886#[test]
887fn test_bitor() {
888 let sigset = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
889 assert!(sigset.has(Signal::SIGABRT));
890 assert!(sigset.has(Signal::SIGSEGV));
891 assert!(!sigset.has(Signal::SIGALRM));
892}
893
894impl core::ops::BitOrAssign for sigset_t {
895 fn bitor_assign(&mut self, rhs: Self) {
896 self.0 |= rhs.0
897 }
898}
899
900#[test]
901fn test_bitorassign() {
902 let mut sigset = sigset_t::from(Signal::SIGABRT);
903 sigset |= sigset_t::from(Signal::SIGSEGV);
904 assert!(sigset.has(Signal::SIGABRT));
905 assert!(sigset.has(Signal::SIGSEGV));
906 assert!(!sigset.has(Signal::SIGALRM));
907}
908
909impl core::ops::BitAnd for sigset_t {
910 type Output = Self;
911
912 fn bitand(self, rhs: Self) -> Self::Output {
913 Self(self.0 & rhs.0)
914 }
915}
916
917#[test]
918fn test_bitand() {
919 let lhs = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
920 let rhs = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGALRM);
921 let and = lhs & rhs;
922 assert!(and.has(Signal::SIGABRT));
923 assert!(!and.has(Signal::SIGSEGV));
924 assert!(!and.has(Signal::SIGALRM));
925}
926
927impl core::ops::BitAndAssign for sigset_t {
928 fn bitand_assign(&mut self, rhs: Self) {
929 self.0 &= rhs.0
930 }
931}
932
933#[test]
934fn test_bitand_assign() {
935 let mut set = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
936 set &= sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGALRM);
937 assert!(set.has(Signal::SIGABRT));
938 assert!(!set.has(Signal::SIGSEGV));
939 assert!(!set.has(Signal::SIGALRM));
940}
941
942impl core::ops::Not for sigset_t {
943 type Output = Self;
944
945 fn not(self) -> Self::Output {
946 Self(!self.0)
947 }
948}
949
950#[test]
951fn test_not() {
952 let set = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
953 let set = !set;
954 assert!(!set.has(Signal::SIGABRT));
955 assert!(!set.has(Signal::SIGSEGV));
956 assert!(set.has(Signal::SIGALRM));
957}
958
959pub type SignalHandlerFn = unsafe extern "C" fn(i32);
960pub type SignalActionFn = unsafe extern "C" fn(i32, *mut siginfo_t, *mut core::ffi::c_void);
961
962pub enum SignalHandler {
963 Handler(SignalHandlerFn),
964 Action(SignalActionFn),
965 SigIgn,
966 SigDfl,
967}
968
969#[allow(non_camel_case_types)]
971pub type linux_sigaction = bindings::linux_sigaction;
972
973#[cfg(target_arch = "x86_64")]
1015#[naked_function::naked]
1016pub unsafe extern "C" fn sigaction_restorer() {
1017 asm!("mov rax, 15", "syscall", "ud2")
1029}
1030static_assertions::const_assert_eq!(bindings::LINUX___NR_rt_sigreturn, 15);
1031
1032#[derive(Copy, Clone)]
1037#[repr(C)]
1038#[allow(non_camel_case_types)]
1039pub struct sigaction(linux_sigaction);
1040unsafe impl shadow_pod::Pod for sigaction {}
1041
1042impl sigaction {
1043 const SIG_DFL: usize = 0;
1048 const SIG_IGN: usize = 1;
1049
1050 pub fn new_raw(
1056 handler: SignalHandler,
1057 flags: SigActionFlags,
1058 mask: sigset_t,
1059 restorer: Option<unsafe extern "C" fn()>,
1060 ) -> Self {
1061 let handler = match handler {
1069 SignalHandler::Handler(h) => {
1070 assert!(!flags.contains(SigActionFlags::SA_SIGINFO));
1071 Some(h)
1072 }
1073 SignalHandler::Action(a) => {
1074 assert!(flags.contains(SigActionFlags::SA_SIGINFO));
1075 Some(unsafe { core::mem::transmute::<SignalActionFn, SignalHandlerFn>(a) })
1076 }
1077 SignalHandler::SigIgn => {
1078 assert!(!flags.contains(SigActionFlags::SA_SIGINFO));
1079 Some(unsafe { core::mem::transmute::<usize, SignalHandlerFn>(Self::SIG_IGN) })
1080 }
1081 SignalHandler::SigDfl => {
1082 assert!(!flags.contains(SigActionFlags::SA_SIGINFO));
1083 static_assertions::const_assert_eq!(sigaction::SIG_DFL, 0);
1084 None
1085 }
1086 };
1087 sigaction(linux_sigaction {
1088 lsa_handler: handler,
1089 lsa_flags: flags.bits(),
1090 lsa_mask: mask.0,
1091 lsa_restorer: restorer,
1092 })
1093 }
1094
1095 pub fn new_with_default_restorer(
1100 handler: SignalHandler,
1101 flags: SigActionFlags,
1102 mask: sigset_t,
1103 ) -> Self {
1104 Self::new_raw(
1105 handler,
1106 flags | SigActionFlags::SA_RESTORER,
1107 mask,
1108 Some(sigaction_restorer),
1109 )
1110 }
1111
1112 pub fn wrap(si: linux_sigaction) -> Self {
1113 Self(si)
1114 }
1115
1116 pub fn wrap_ref(si: &linux_sigaction) -> &Self {
1117 unsafe { &*(core::ptr::from_ref(si) as *const Self) }
1118 }
1119
1120 pub fn wrap_mut(si: &mut linux_sigaction) -> &mut Self {
1121 unsafe { &mut *(core::ptr::from_mut(si) as *mut Self) }
1122 }
1123
1124 pub unsafe fn peel(si: Self) -> linux_sigaction {
1129 si.0
1130 }
1131
1132 pub fn flags(&self) -> Option<SigActionFlags> {
1133 SigActionFlags::from_bits(self.0.lsa_flags)
1134 }
1135
1136 pub fn flags_retain(&self) -> SigActionFlags {
1137 SigActionFlags::from_bits_retain(self.0.lsa_flags)
1138 }
1139
1140 pub fn mask(&self) -> sigset_t {
1141 sigset_t::wrap(self.0.lsa_mask)
1142 }
1143
1144 pub unsafe fn handler(&self) -> SignalHandler {
1150 let as_usize = self.as_usize();
1151 if as_usize == Self::SIG_IGN {
1152 SignalHandler::SigIgn
1153 } else if as_usize == Self::SIG_DFL {
1154 SignalHandler::SigDfl
1155 } else if self.flags_retain().contains(SigActionFlags::SA_SIGINFO) {
1156 let handler_fn: SignalHandlerFn = self.0.lsa_handler.unwrap();
1159 let action_fn: SignalActionFn =
1166 unsafe { core::mem::transmute::<SignalHandlerFn, SignalActionFn>(handler_fn) };
1167 SignalHandler::Action(action_fn)
1168 } else {
1169 SignalHandler::Handler(self.0.lsa_handler.unwrap())
1170 }
1171 }
1172
1173 fn as_usize(&self) -> usize {
1174 self.0.lsa_handler.map(|f| f as usize).unwrap_or(0)
1175 }
1176
1177 pub fn is_ignore(&self) -> bool {
1178 self.as_usize() == Self::SIG_IGN
1179 }
1180
1181 pub fn is_default(&self) -> bool {
1182 self.as_usize() == Self::SIG_DFL
1183 }
1184}
1185
1186impl Default for sigaction {
1187 fn default() -> Self {
1188 unsafe { core::mem::zeroed() }
1189 }
1190}
1191
1192#[derive(Eq, PartialEq, Debug)]
1194#[repr(C)]
1195pub enum LinuxDefaultAction {
1196 TERM,
1197 IGN,
1198 CORE,
1199 STOP,
1200 CONT,
1201}
1202
1203pub fn defaultaction(sig: Signal) -> LinuxDefaultAction {
1204 use LinuxDefaultAction as Action;
1205 match sig {
1206 Signal::SIGCONT => Action::CONT,
1207 Signal::SIGABRT
1209 | Signal::SIGBUS
1210 | Signal::SIGFPE
1211 | Signal::SIGILL
1212 | Signal::SIGQUIT
1213 | Signal::SIGSEGV
1214 | Signal::SIGSYS
1215 | Signal::SIGTRAP
1216 | Signal::SIGXCPU
1217 | Signal::SIGXFSZ => Action::CORE,
1218 Signal::SIGCHLD
1220 | Signal::SIGURG
1221 | Signal::SIGWINCH => Action::IGN,
1222 Signal::SIGSTOP
1223 | Signal::SIGTSTP
1224 | Signal::SIGTTIN
1225 | Signal::SIGTTOU => Action::STOP,
1226 Signal::SIGALRM
1227 | Signal::SIGHUP
1229 | Signal::SIGINT
1230 | Signal::SIGIO
1232 | Signal::SIGKILL
1233 | Signal::SIGPIPE
1235 | Signal::SIGPROF
1236 | Signal::SIGPWR
1237 | Signal::SIGSTKFLT
1238 | Signal::SIGTERM
1239 | Signal::SIGUSR1
1240 | Signal::SIGUSR2
1241 | Signal::SIGVTALRM => Action::TERM,
1242 other => {
1244 assert!(other.is_realtime());
1245 Action::TERM
1249 },
1250 }
1251}
1252
1253pub fn kill_raw(pid: kernel_pid_t, sig: i32) -> Result<(), Errno> {
1255 unsafe { syscall!(linux_syscall::SYS_kill, pid, sig) }
1256 .check()
1257 .map_err(Errno::from)
1258}
1259
1260pub fn kill_process(pid: Pid, sig: Option<Signal>) -> Result<(), Errno> {
1262 kill_raw(pid.as_raw_nonzero().into(), Signal::as_raw(sig))
1263}
1264
1265pub fn kill_process_group(pid: Pid, sig: Option<Signal>) -> Result<(), Errno> {
1267 kill_raw(-i32::from(pid.as_raw_nonzero()), Signal::as_raw(sig))
1268}
1269
1270pub fn kill_current_process_group(sig: Option<Signal>) -> Result<(), Errno> {
1272 kill_raw(0, Signal::as_raw(sig))
1273}
1274
1275pub unsafe fn rt_sigaction_raw(
1287 signo: i32,
1288 new_action: *const sigaction,
1289 old_action: *mut sigaction,
1290 sigsetsize: usize,
1291) -> Result<(), Errno> {
1292 unsafe {
1293 syscall!(
1294 linux_syscall::SYS_rt_sigaction,
1295 signo,
1296 new_action,
1297 old_action,
1298 sigsetsize
1299 )
1300 }
1301 .check()
1302 .map_err(Errno::from)
1303}
1304
1305pub unsafe fn rt_sigaction(
1315 signal: Signal,
1316 new_action: &sigaction,
1317 old_action: Option<&mut sigaction>,
1318) -> Result<(), Errno> {
1319 unsafe {
1320 rt_sigaction_raw(
1321 signal.as_i32(),
1322 new_action,
1323 old_action
1324 .map(core::ptr::from_mut)
1325 .unwrap_or(core::ptr::null_mut()),
1326 core::mem::size_of::<sigset_t>(),
1327 )
1328 }
1329}
1330
1331#[allow(non_camel_case_types)]
1333#[repr(i32)]
1334#[derive(Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
1335pub enum SigProcMaskAction {
1336 SIG_BLOCK = const_conversions::i32_from_u32(bindings::LINUX_SIG_BLOCK),
1337 SIG_UNBLOCK = const_conversions::i32_from_u32(bindings::LINUX_SIG_UNBLOCK),
1338 SIG_SETMASK = const_conversions::i32_from_u32(bindings::LINUX_SIG_SETMASK),
1339}
1340
1341pub unsafe fn rt_sigprocmask_raw(
1348 how: i32,
1349 sigset_in: *const sigset_t,
1350 sigset_out: *mut sigset_t,
1351 sigset_sz: usize,
1352) -> Result<(), Errno> {
1353 unsafe {
1354 syscall!(
1355 linux_syscall::SYS_rt_sigprocmask,
1356 how,
1357 sigset_in,
1358 sigset_out,
1359 sigset_sz,
1360 )
1361 .check()
1362 .map_err(Errno::from)
1363 }
1364}
1365
1366pub fn rt_sigprocmask(
1368 how: SigProcMaskAction,
1369 sigset_in: &sigset_t,
1370 sigset_out: Option<&mut sigset_t>,
1371) -> Result<(), Errno> {
1372 unsafe {
1373 rt_sigprocmask_raw(
1374 how.into(),
1375 sigset_in,
1376 sigset_out
1377 .map(core::ptr::from_mut)
1378 .unwrap_or(core::ptr::null_mut()),
1379 core::mem::size_of::<sigset_t>(),
1380 )
1381 }
1382}
1383
1384#[cfg(test)]
1385mod rt_sigaction_tests {
1386 use core::sync::atomic::AtomicI32;
1387
1388 use shadow_pod::zeroed;
1389
1390 use super::*;
1391
1392 #[cfg(not(miri))]
1399 #[test]
1400 fn test_rt_sigaction() {
1401 static CALL_COUNTER: AtomicI32 = AtomicI32::new(0);
1403 extern "C" fn handler(_signo: i32) {
1404 CALL_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
1405 }
1406
1407 let action = sigaction::new_with_default_restorer(
1409 SignalHandler::Handler(handler),
1410 SigActionFlags::empty(),
1411 sigset_t::EMPTY,
1412 );
1413
1414 let signal = Signal::SIGUSR2;
1416
1417 let mut old_action = zeroed();
1419 unsafe { rt_sigaction(signal, &action, Some(&mut old_action)) }.unwrap();
1420
1421 let mut old_mask: sigset_t = sigset_t::EMPTY;
1423 let mask = sigset_t::from(signal);
1424 rt_sigprocmask(SigProcMaskAction::SIG_UNBLOCK, &mask, Some(&mut old_mask)).unwrap();
1425
1426 let pid = rustix::process::getpid();
1429 let tid = rustix::thread::gettid();
1430 unsafe {
1431 linux_syscall::syscall!(
1432 linux_syscall::SYS_tgkill,
1433 pid.as_raw_nonzero().get(),
1434 tid.as_raw_nonzero().get(),
1435 signal.as_i32()
1436 )
1437 }
1438 .check()
1439 .unwrap();
1440
1441 assert_eq!(CALL_COUNTER.load(core::sync::atomic::Ordering::Relaxed), 1);
1443
1444 rt_sigprocmask(SigProcMaskAction::SIG_SETMASK, &old_mask, None).unwrap();
1446 unsafe { rt_sigaction(signal, &old_action, None) }.unwrap();
1447 }
1448}
1449
1450pub use bindings::linux_stack_t;
1451#[allow(non_camel_case_types)]
1452pub type stack_t = linux_stack_t;
1453
1454impl stack_t {
1455 pub fn new(sp: *mut core::ffi::c_void, flags: SigAltStackFlags, size: usize) -> Self {
1456 Self {
1457 ss_sp: sp,
1458 ss_flags: flags.bits(),
1459 ss_size: size.try_into().unwrap(),
1460 }
1461 }
1462
1463 pub fn flags_retain(&self) -> SigAltStackFlags {
1464 SigAltStackFlags::from_bits_retain(self.ss_flags)
1465 }
1466
1467 pub fn sp(&self) -> *mut core::ffi::c_void {
1468 self.ss_sp
1469 }
1470
1471 pub fn size(&self) -> usize {
1472 self.ss_size.try_into().unwrap()
1473 }
1474}
1475
1476pub const LINUX_SS_AUTODISARM: u32 = 1 << 31;
1479bitflags::bitflags! {
1480 #[repr(transparent)]
1483 #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
1484 pub struct SigAltStackFlags: i32 {
1485 const SS_AUTODISARM = i32_from_u32_allowing_wraparound(LINUX_SS_AUTODISARM);
1487 const SS_ONSTACK = const_conversions::i32_from_u32(bindings::LINUX_SS_ONSTACK);
1488 const SS_DISABLE= const_conversions::i32_from_u32(bindings::LINUX_SS_DISABLE);
1489 }
1490}
1491unsafe impl VirtualAddressSpaceIndependent for SigAltStackFlags {}
1493
1494pub unsafe fn sigaltstack_raw(
1500 new_stack: *const stack_t,
1501 old_stack: *mut stack_t,
1502) -> Result<(), Errno> {
1503 unsafe { syscall!(linux_syscall::SYS_sigaltstack, new_stack, old_stack) }
1504 .check()
1505 .map_err(Errno::from)
1506}
1507
1508pub unsafe fn sigaltstack(
1512 new_stack: Option<&stack_t>,
1513 old_stack: Option<&mut stack_t>,
1514) -> Result<(), Errno> {
1515 unsafe {
1516 sigaltstack_raw(
1517 new_stack
1518 .map(core::ptr::from_ref)
1519 .unwrap_or(core::ptr::null()),
1520 old_stack
1521 .map(core::ptr::from_mut)
1522 .unwrap_or(core::ptr::null_mut()),
1523 )
1524 }
1525}
1526
1527pub fn tgkill_raw(tgid: kernel_pid_t, tid: kernel_pid_t, signo: i32) -> Result<(), Errno> {
1528 unsafe { syscall!(linux_syscall::SYS_tgkill, tgid, tid, signo) }
1529 .check()
1530 .map_err(Errno::from)
1531}
1532
1533pub fn tgkill(tgid: Pid, tid: Pid, signal: Option<Signal>) -> Result<(), Errno> {
1534 tgkill_raw(
1535 Pid::as_raw(Some(tgid)),
1536 Pid::as_raw(Some(tid)),
1537 signal.map(i32::from).unwrap_or(0),
1538 )
1539}
1540
1541mod export {
1542 use crate::bindings::{linux_siginfo_t, linux_sigset_t};
1543
1544 use super::*;
1545
1546 #[unsafe(no_mangle)]
1547 pub extern "C-unwind" fn linux_signal_is_valid(signo: i32) -> bool {
1548 Signal::try_from(signo).is_ok()
1549 }
1550
1551 #[unsafe(no_mangle)]
1552 pub extern "C-unwind" fn linux_signal_is_realtime(signo: i32) -> bool {
1553 let Ok(signal) = Signal::try_from(signo) else {
1554 return false;
1555 };
1556 signal.is_realtime()
1557 }
1558
1559 #[unsafe(no_mangle)]
1560 pub extern "C-unwind" fn linux_sigemptyset() -> linux_sigset_t {
1561 sigset_t::EMPTY.0
1562 }
1563
1564 #[unsafe(no_mangle)]
1565 pub extern "C-unwind" fn linux_sigfullset() -> linux_sigset_t {
1566 sigset_t::FULL.0
1567 }
1568
1569 #[unsafe(no_mangle)]
1570 pub unsafe extern "C-unwind" fn linux_sigaddset(set: *mut linux_sigset_t, signo: i32) {
1571 let set = sigset_t::wrap_mut(unsafe { set.as_mut().unwrap() });
1572 let signo = Signal::try_from(signo).unwrap();
1573 set.add(signo);
1574 }
1575
1576 #[unsafe(no_mangle)]
1577 pub unsafe extern "C-unwind" fn linux_sigdelset(set: *mut linux_sigset_t, signo: i32) {
1578 let set = sigset_t::wrap_mut(unsafe { set.as_mut().unwrap() });
1579 let signo = Signal::try_from(signo).unwrap();
1580 set.del(signo);
1581 }
1582
1583 #[unsafe(no_mangle)]
1584 pub unsafe extern "C-unwind" fn linux_sigismember(
1585 set: *const linux_sigset_t,
1586 signo: i32,
1587 ) -> bool {
1588 let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1589 set.has(signo.try_into().unwrap())
1590 }
1591
1592 #[unsafe(no_mangle)]
1593 pub unsafe extern "C-unwind" fn linux_sigisemptyset(set: *const linux_sigset_t) -> bool {
1594 let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1595 set.is_empty()
1596 }
1597
1598 #[unsafe(no_mangle)]
1599 pub unsafe extern "C-unwind" fn linux_sigorset(
1600 lhs: *const linux_sigset_t,
1601 rhs: *const linux_sigset_t,
1602 ) -> linux_sigset_t {
1603 let lhs = unsafe { lhs.as_ref().unwrap() };
1604 let rhs = unsafe { rhs.as_ref().unwrap() };
1605 sigset_t(*lhs | *rhs).0
1606 }
1607
1608 #[unsafe(no_mangle)]
1609 pub unsafe extern "C-unwind" fn linux_sigandset(
1610 lhs: *const linux_sigset_t,
1611 rhs: *const linux_sigset_t,
1612 ) -> linux_sigset_t {
1613 let lhs = unsafe { lhs.as_ref().unwrap() };
1614 let rhs = unsafe { rhs.as_ref().unwrap() };
1615 sigset_t(*lhs & *rhs).0
1616 }
1617
1618 #[unsafe(no_mangle)]
1619 pub unsafe extern "C-unwind" fn linux_signotset(set: *const linux_sigset_t) -> linux_sigset_t {
1620 let set = unsafe { set.as_ref().unwrap() };
1621 sigset_t(!*set).0
1622 }
1623
1624 #[unsafe(no_mangle)]
1625 pub unsafe extern "C-unwind" fn linux_siglowest(set: *const linux_sigset_t) -> i32 {
1626 let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1627 match set.lowest() {
1628 Some(s) => s.into(),
1629 None => 0,
1630 }
1631 }
1632
1633 #[unsafe(no_mangle)]
1634 pub extern "C-unwind" fn linux_defaultAction(signo: i32) -> LinuxDefaultAction {
1635 let sig = Signal::try_from(signo).unwrap();
1636 defaultaction(sig)
1637 }
1638
1639 #[unsafe(no_mangle)]
1640 pub unsafe extern "C-unwind" fn linux_kill(pid: i32, sig: i32) -> i32 {
1641 match kill_raw(pid, sig) {
1642 Ok(()) => 0,
1643 Err(e) => e.to_negated_i32(),
1644 }
1645 }
1646
1647 #[unsafe(no_mangle)]
1649 pub unsafe extern "C-unwind" fn linux_sigaction_handler(
1650 sa: *const linux_sigaction,
1651 ) -> Option<unsafe extern "C" fn(i32)> {
1652 let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1653 match unsafe { sa.handler() } {
1654 SignalHandler::Handler(h) => Some(h),
1655 _ => None,
1656 }
1657 }
1658
1659 #[unsafe(no_mangle)]
1661 pub unsafe extern "C-unwind" fn linux_sigaction_action(
1662 sa: *const linux_sigaction,
1663 ) -> Option<unsafe extern "C" fn(i32, *mut linux_siginfo_t, *mut core::ffi::c_void)> {
1664 let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1665 match unsafe { sa.handler() } {
1666 SignalHandler::Action(h) =>
1667 {
1671 Some(unsafe {
1672 core::mem::transmute::<
1673 unsafe extern "C" fn(i32, *mut siginfo_t, *mut core::ffi::c_void),
1674 unsafe extern "C" fn(i32, *mut linux_siginfo_t, *mut core::ffi::c_void),
1675 >(h)
1676 })
1677 }
1678 _ => None,
1679 }
1680 }
1681
1682 #[unsafe(no_mangle)]
1683 pub unsafe extern "C-unwind" fn linux_sigaction_is_ign(sa: *const linux_sigaction) -> bool {
1684 let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1685 matches!(unsafe { sa.handler() }, SignalHandler::SigIgn)
1686 }
1687
1688 #[unsafe(no_mangle)]
1689 pub unsafe extern "C-unwind" fn linux_sigaction_is_dfl(sa: *const linux_sigaction) -> bool {
1690 let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1691 matches!(unsafe { sa.handler() }, SignalHandler::SigDfl)
1692 }
1693}