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 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 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;
1453unsafe impl Pod for stack_t {}
1454
1455impl stack_t {
1456    pub fn new(sp: *mut core::ffi::c_void, flags: SigAltStackFlags, size: usize) -> Self {
1457        Self {
1458            ss_sp: sp,
1459            ss_flags: flags.bits(),
1460            ss_size: size.try_into().unwrap(),
1461        }
1462    }
1463
1464    pub fn flags_retain(&self) -> SigAltStackFlags {
1465        SigAltStackFlags::from_bits_retain(self.ss_flags)
1466    }
1467
1468    pub fn sp(&self) -> *mut core::ffi::c_void {
1469        self.ss_sp
1470    }
1471
1472    pub fn size(&self) -> usize {
1473        self.ss_size.try_into().unwrap()
1474    }
1475}
1476
1477pub const LINUX_SS_AUTODISARM: u32 = 1 << 31;
1480bitflags::bitflags! {
1481    #[repr(transparent)]
1484    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
1485    pub struct SigAltStackFlags: i32 {
1486        const SS_AUTODISARM = i32_from_u32_allowing_wraparound(LINUX_SS_AUTODISARM);
1488        const SS_ONSTACK = const_conversions::i32_from_u32(bindings::LINUX_SS_ONSTACK);
1489        const SS_DISABLE= const_conversions::i32_from_u32(bindings::LINUX_SS_DISABLE);
1490    }
1491}
1492unsafe impl VirtualAddressSpaceIndependent for SigAltStackFlags {}
1494
1495pub unsafe fn sigaltstack_raw(
1501    new_stack: *const stack_t,
1502    old_stack: *mut stack_t,
1503) -> Result<(), Errno> {
1504    unsafe { syscall!(linux_syscall::SYS_sigaltstack, new_stack, old_stack) }
1505        .check()
1506        .map_err(Errno::from)
1507}
1508
1509pub unsafe fn sigaltstack(
1513    new_stack: Option<&stack_t>,
1514    old_stack: Option<&mut stack_t>,
1515) -> Result<(), Errno> {
1516    unsafe {
1517        sigaltstack_raw(
1518            new_stack
1519                .map(core::ptr::from_ref)
1520                .unwrap_or(core::ptr::null()),
1521            old_stack
1522                .map(core::ptr::from_mut)
1523                .unwrap_or(core::ptr::null_mut()),
1524        )
1525    }
1526}
1527
1528pub fn tgkill_raw(tgid: kernel_pid_t, tid: kernel_pid_t, signo: i32) -> Result<(), Errno> {
1529    unsafe { syscall!(linux_syscall::SYS_tgkill, tgid, tid, signo) }
1530        .check()
1531        .map_err(Errno::from)
1532}
1533
1534pub fn tgkill(tgid: Pid, tid: Pid, signal: Option<Signal>) -> Result<(), Errno> {
1535    tgkill_raw(
1536        Pid::as_raw(Some(tgid)),
1537        Pid::as_raw(Some(tid)),
1538        signal.map(i32::from).unwrap_or(0),
1539    )
1540}
1541
1542mod export {
1543    use crate::bindings::{linux_siginfo_t, linux_sigset_t};
1544
1545    use super::*;
1546
1547    #[unsafe(no_mangle)]
1548    pub extern "C-unwind" fn linux_signal_is_valid(signo: i32) -> bool {
1549        Signal::try_from(signo).is_ok()
1550    }
1551
1552    #[unsafe(no_mangle)]
1553    pub extern "C-unwind" fn linux_signal_is_realtime(signo: i32) -> bool {
1554        let Ok(signal) = Signal::try_from(signo) else {
1555            return false;
1556        };
1557        signal.is_realtime()
1558    }
1559
1560    #[unsafe(no_mangle)]
1561    pub extern "C-unwind" fn linux_sigemptyset() -> linux_sigset_t {
1562        sigset_t::EMPTY.0
1563    }
1564
1565    #[unsafe(no_mangle)]
1566    pub extern "C-unwind" fn linux_sigfullset() -> linux_sigset_t {
1567        sigset_t::FULL.0
1568    }
1569
1570    #[unsafe(no_mangle)]
1571    pub unsafe extern "C-unwind" fn linux_sigaddset(set: *mut linux_sigset_t, signo: i32) {
1572        let set = sigset_t::wrap_mut(unsafe { set.as_mut().unwrap() });
1573        let signo = Signal::try_from(signo).unwrap();
1574        set.add(signo);
1575    }
1576
1577    #[unsafe(no_mangle)]
1578    pub unsafe extern "C-unwind" fn linux_sigdelset(set: *mut linux_sigset_t, signo: i32) {
1579        let set = sigset_t::wrap_mut(unsafe { set.as_mut().unwrap() });
1580        let signo = Signal::try_from(signo).unwrap();
1581        set.del(signo);
1582    }
1583
1584    #[unsafe(no_mangle)]
1585    pub unsafe extern "C-unwind" fn linux_sigismember(
1586        set: *const linux_sigset_t,
1587        signo: i32,
1588    ) -> bool {
1589        let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1590        set.has(signo.try_into().unwrap())
1591    }
1592
1593    #[unsafe(no_mangle)]
1594    pub unsafe extern "C-unwind" fn linux_sigisemptyset(set: *const linux_sigset_t) -> bool {
1595        let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1596        set.is_empty()
1597    }
1598
1599    #[unsafe(no_mangle)]
1600    pub unsafe extern "C-unwind" fn linux_sigorset(
1601        lhs: *const linux_sigset_t,
1602        rhs: *const linux_sigset_t,
1603    ) -> linux_sigset_t {
1604        let lhs = unsafe { lhs.as_ref().unwrap() };
1605        let rhs = unsafe { rhs.as_ref().unwrap() };
1606        sigset_t(*lhs | *rhs).0
1607    }
1608
1609    #[unsafe(no_mangle)]
1610    pub unsafe extern "C-unwind" fn linux_sigandset(
1611        lhs: *const linux_sigset_t,
1612        rhs: *const linux_sigset_t,
1613    ) -> linux_sigset_t {
1614        let lhs = unsafe { lhs.as_ref().unwrap() };
1615        let rhs = unsafe { rhs.as_ref().unwrap() };
1616        sigset_t(*lhs & *rhs).0
1617    }
1618
1619    #[unsafe(no_mangle)]
1620    pub unsafe extern "C-unwind" fn linux_signotset(set: *const linux_sigset_t) -> linux_sigset_t {
1621        let set = unsafe { set.as_ref().unwrap() };
1622        sigset_t(!*set).0
1623    }
1624
1625    #[unsafe(no_mangle)]
1626    pub unsafe extern "C-unwind" fn linux_siglowest(set: *const linux_sigset_t) -> i32 {
1627        let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1628        match set.lowest() {
1629            Some(s) => s.into(),
1630            None => 0,
1631        }
1632    }
1633
1634    #[unsafe(no_mangle)]
1635    pub extern "C-unwind" fn linux_defaultAction(signo: i32) -> LinuxDefaultAction {
1636        let sig = Signal::try_from(signo).unwrap();
1637        defaultaction(sig)
1638    }
1639
1640    #[unsafe(no_mangle)]
1641    pub unsafe extern "C-unwind" fn linux_kill(pid: i32, sig: i32) -> i32 {
1642        match kill_raw(pid, sig) {
1643            Ok(()) => 0,
1644            Err(e) => e.to_negated_i32(),
1645        }
1646    }
1647
1648    #[unsafe(no_mangle)]
1650    pub unsafe extern "C-unwind" fn linux_sigaction_handler(
1651        sa: *const linux_sigaction,
1652    ) -> Option<unsafe extern "C" fn(i32)> {
1653        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1654        match unsafe { sa.handler() } {
1655            SignalHandler::Handler(h) => Some(h),
1656            _ => None,
1657        }
1658    }
1659
1660    #[unsafe(no_mangle)]
1662    pub unsafe extern "C-unwind" fn linux_sigaction_action(
1663        sa: *const linux_sigaction,
1664    ) -> Option<unsafe extern "C" fn(i32, *mut linux_siginfo_t, *mut core::ffi::c_void)> {
1665        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1666        match unsafe { sa.handler() } {
1667            SignalHandler::Action(h) =>
1668            {
1672                Some(unsafe {
1673                    core::mem::transmute::<
1674                        unsafe extern "C" fn(i32, *mut siginfo_t, *mut core::ffi::c_void),
1675                        unsafe extern "C" fn(i32, *mut linux_siginfo_t, *mut core::ffi::c_void),
1676                    >(h)
1677                })
1678            }
1679            _ => None,
1680        }
1681    }
1682
1683    #[unsafe(no_mangle)]
1684    pub unsafe extern "C-unwind" fn linux_sigaction_is_ign(sa: *const linux_sigaction) -> bool {
1685        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1686        matches!(unsafe { sa.handler() }, SignalHandler::SigIgn)
1687    }
1688
1689    #[unsafe(no_mangle)]
1690    pub unsafe extern "C-unwind" fn linux_sigaction_is_dfl(sa: *const linux_sigaction) -> bool {
1691        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1692        matches!(unsafe { sa.handler() }, SignalHandler::SigDfl)
1693    }
1694}