1#![allow(unsafe_code)]
13
14use crate::backend::c;
15use core::fmt;
16use core::num::NonZeroI32;
17
18#[doc(alias = "SIGRTMIN")]
45#[doc(alias = "SIGRTMAX")]
46#[derive(Copy, Clone, Eq, PartialEq)]
47#[repr(transparent)]
48pub struct Signal(NonZeroI32);
49
50#[rustfmt::skip]
52impl Signal {
53    pub const HUP: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGHUP) });
55    pub const INT: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGINT) });
57    pub const QUIT: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGQUIT) });
59    pub const ILL: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGILL) });
61    pub const TRAP: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGTRAP) });
63    #[doc(alias = "IOT")]
65    #[doc(alias = "ABRT")]
66    pub const ABORT: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGABRT) });
67    pub const BUS: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGBUS) });
69    pub const FPE: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGFPE) });
71    pub const KILL: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGKILL) });
73    #[cfg(not(target_os = "vita"))]
75    pub const USR1: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGUSR1) });
76    pub const SEGV: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGSEGV) });
78    #[cfg(not(target_os = "vita"))]
80    pub const USR2: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGUSR2) });
81    pub const PIPE: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGPIPE) });
83    #[doc(alias = "ALRM")]
85    pub const ALARM: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGALRM) });
86    pub const TERM: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGTERM) });
88    #[cfg(not(any(
90        bsd,
91        solarish,
92        target_os = "aix",
93        target_os = "cygwin",
94        target_os = "haiku",
95        target_os = "horizon",
96        target_os = "hurd",
97        target_os = "nto",
98        target_os = "vita",
99        all(
100            linux_kernel,
101            any(
102                target_arch = "mips",
103                target_arch = "mips32r6",
104                target_arch = "mips64",
105                target_arch = "mips64r6",
106                target_arch = "sparc",
107                target_arch = "sparc64"
108            ),
109        ),
110    )))]
111    pub const STKFLT: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGSTKFLT) });
112    #[cfg(not(target_os = "vita"))]
114    #[doc(alias = "CHLD")]
115    pub const CHILD: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGCHLD) });
116    #[cfg(not(target_os = "vita"))]
118    pub const CONT: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGCONT) });
119    #[cfg(not(target_os = "vita"))]
121    pub const STOP: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGSTOP) });
122    #[cfg(not(target_os = "vita"))]
124    pub const TSTP: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGTSTP) });
125    #[cfg(not(target_os = "vita"))]
127    pub const TTIN: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGTTIN) });
128    #[cfg(not(target_os = "vita"))]
130    pub const TTOU: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGTTOU) });
131    #[cfg(not(target_os = "vita"))]
133    pub const URG: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGURG) });
134    #[cfg(not(target_os = "vita"))]
136    pub const XCPU: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGXCPU) });
137    #[cfg(not(target_os = "vita"))]
139    pub const XFSZ: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGXFSZ) });
140    #[cfg(not(target_os = "vita"))]
142    #[doc(alias = "VTALRM")]
143    pub const VTALARM: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGVTALRM) });
144    #[cfg(not(target_os = "vita"))]
146    pub const PROF: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGPROF) });
147    #[cfg(not(target_os = "vita"))]
149    pub const WINCH: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGWINCH) });
150    #[doc(alias = "POLL")]
152    #[cfg(not(any(target_os = "haiku", target_os = "vita")))]
153    pub const IO: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGIO) });
154    #[cfg(not(any(
156        bsd,
157        target_os = "haiku",
158        target_os = "horizon",
159        target_os = "hurd",
160        target_os = "vita"
161    )))]
162    #[doc(alias = "PWR")]
163    pub const POWER: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGPWR) });
164    #[doc(alias = "UNUSED")]
166    pub const SYS: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGSYS) });
167    #[cfg(any(
169        bsd,
170        solarish,
171        target_os = "aix",
172        target_os = "hermit",
173        all(
174            linux_kernel,
175            any(
176                target_arch = "mips",
177                target_arch = "mips32r6",
178                target_arch = "mips64",
179                target_arch = "mips64r6",
180                target_arch = "sparc",
181                target_arch = "sparc64"
182            )
183        )
184    ))]
185    pub const EMT: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGEMT) });
186    #[cfg(bsd)]
188    pub const INFO: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGINFO) });
189    #[cfg(target_os = "freebsd")]
191    #[doc(alias = "LWP")]
192    pub const THR: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGTHR) });
193    #[cfg(target_os = "freebsd")]
195    pub const LIBRT: Self = Self(unsafe { NonZeroI32::new_unchecked(c::SIGLIBRT) });
196}
197
198impl Signal {
199    #[inline]
203    pub const fn as_raw(self) -> i32 {
204        self.0.get()
205    }
206
207    #[inline]
209    pub const fn as_raw_nonzero(self) -> NonZeroI32 {
210        self.0
211    }
212
213    #[inline]
232    pub const unsafe fn from_raw_unchecked(sig: i32) -> Self {
233        Self::from_raw_nonzero_unchecked(NonZeroI32::new_unchecked(sig))
234    }
235
236    #[inline]
255    pub const unsafe fn from_raw_nonzero_unchecked(sig: NonZeroI32) -> Self {
256        Self(sig)
257    }
258
259    pub const fn from_named_raw(sig: i32) -> Option<Self> {
272        if let Some(sig) = NonZeroI32::new(sig) {
273            Self::from_named_raw_nonzero(sig)
274        } else {
275            None
276        }
277    }
278
279    pub const fn from_named_raw_nonzero(sig: NonZeroI32) -> Option<Self> {
292        match sig.get() {
293            c::SIGHUP => Some(Self::HUP),
294            c::SIGINT => Some(Self::INT),
295            c::SIGQUIT => Some(Self::QUIT),
296            c::SIGILL => Some(Self::ILL),
297            c::SIGTRAP => Some(Self::TRAP),
298            c::SIGABRT => Some(Self::ABORT),
299            c::SIGBUS => Some(Self::BUS),
300            c::SIGFPE => Some(Self::FPE),
301            c::SIGKILL => Some(Self::KILL),
302            #[cfg(not(target_os = "vita"))]
303            c::SIGUSR1 => Some(Self::USR1),
304            c::SIGSEGV => Some(Self::SEGV),
305            #[cfg(not(target_os = "vita"))]
306            c::SIGUSR2 => Some(Self::USR2),
307            c::SIGPIPE => Some(Self::PIPE),
308            c::SIGALRM => Some(Self::ALARM),
309            c::SIGTERM => Some(Self::TERM),
310            #[cfg(not(any(
311                bsd,
312                solarish,
313                target_os = "aix",
314                target_os = "cygwin",
315                target_os = "haiku",
316                target_os = "horizon",
317                target_os = "hurd",
318                target_os = "nto",
319                target_os = "vita",
320                all(
321                    linux_kernel,
322                    any(
323                        target_arch = "mips",
324                        target_arch = "mips32r6",
325                        target_arch = "mips64",
326                        target_arch = "mips64r6",
327                        target_arch = "sparc",
328                        target_arch = "sparc64"
329                    ),
330                )
331            )))]
332            c::SIGSTKFLT => Some(Self::STKFLT),
333            #[cfg(not(target_os = "vita"))]
334            c::SIGCHLD => Some(Self::CHILD),
335            #[cfg(not(target_os = "vita"))]
336            c::SIGCONT => Some(Self::CONT),
337            #[cfg(not(target_os = "vita"))]
338            c::SIGSTOP => Some(Self::STOP),
339            #[cfg(not(target_os = "vita"))]
340            c::SIGTSTP => Some(Self::TSTP),
341            #[cfg(not(target_os = "vita"))]
342            c::SIGTTIN => Some(Self::TTIN),
343            #[cfg(not(target_os = "vita"))]
344            c::SIGTTOU => Some(Self::TTOU),
345            #[cfg(not(target_os = "vita"))]
346            c::SIGURG => Some(Self::URG),
347            #[cfg(not(target_os = "vita"))]
348            c::SIGXCPU => Some(Self::XCPU),
349            #[cfg(not(target_os = "vita"))]
350            c::SIGXFSZ => Some(Self::XFSZ),
351            #[cfg(not(target_os = "vita"))]
352            c::SIGVTALRM => Some(Self::VTALARM),
353            #[cfg(not(target_os = "vita"))]
354            c::SIGPROF => Some(Self::PROF),
355            #[cfg(not(target_os = "vita"))]
356            c::SIGWINCH => Some(Self::WINCH),
357            #[cfg(not(any(target_os = "haiku", target_os = "vita")))]
358            c::SIGIO => Some(Self::IO),
359            #[cfg(not(any(
360                bsd,
361                target_os = "haiku",
362                target_os = "horizon",
363                target_os = "hurd",
364                target_os = "vita"
365            )))]
366            c::SIGPWR => Some(Self::POWER),
367            c::SIGSYS => Some(Self::SYS),
368            #[cfg(any(
369                bsd,
370                solarish,
371                target_os = "aix",
372                target_os = "hermit",
373                all(
374                    linux_kernel,
375                    any(
376                        target_arch = "mips",
377                        target_arch = "mips32r6",
378                        target_arch = "mips64",
379                        target_arch = "mips64r6",
380                        target_arch = "sparc",
381                        target_arch = "sparc64"
382                    )
383                )
384            ))]
385            c::SIGEMT => Some(Self::EMT),
386            #[cfg(bsd)]
387            c::SIGINFO => Some(Self::INFO),
388            #[cfg(target_os = "freebsd")]
389            c::SIGTHR => Some(Self::THR),
390            #[cfg(target_os = "freebsd")]
391            c::SIGLIBRT => Some(Self::LIBRT),
392
393            _ => None,
394        }
395    }
396}
397
398impl fmt::Debug for Signal {
399    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
400        match *self {
401            Self::HUP => "Signal::HUP".fmt(f),
402            Self::INT => "Signal::INT".fmt(f),
403            Self::QUIT => "Signal::QUIT".fmt(f),
404            Self::ILL => "Signal::ILL".fmt(f),
405            Self::TRAP => "Signal::TRAP".fmt(f),
406            Self::ABORT => "Signal::ABORT".fmt(f),
407            Self::BUS => "Signal::BUS".fmt(f),
408            Self::FPE => "Signal::FPE".fmt(f),
409            Self::KILL => "Signal::KILL".fmt(f),
410            #[cfg(not(target_os = "vita"))]
411            Self::USR1 => "Signal::USR1".fmt(f),
412            Self::SEGV => "Signal::SEGV".fmt(f),
413            #[cfg(not(target_os = "vita"))]
414            Self::USR2 => "Signal::USR2".fmt(f),
415            Self::PIPE => "Signal::PIPE".fmt(f),
416            Self::ALARM => "Signal::ALARM".fmt(f),
417            Self::TERM => "Signal::TERM".fmt(f),
418            #[cfg(not(any(
419                bsd,
420                solarish,
421                target_os = "aix",
422                target_os = "cygwin",
423                target_os = "haiku",
424                target_os = "horizon",
425                target_os = "hurd",
426                target_os = "nto",
427                target_os = "vita",
428                all(
429                    linux_kernel,
430                    any(
431                        target_arch = "mips",
432                        target_arch = "mips32r6",
433                        target_arch = "mips64",
434                        target_arch = "mips64r6",
435                        target_arch = "sparc",
436                        target_arch = "sparc64"
437                    ),
438                ),
439            )))]
440            Self::STKFLT => "Signal::STKFLT".fmt(f),
441            #[cfg(not(target_os = "vita"))]
442            Self::CHILD => "Signal::CHILD".fmt(f),
443            #[cfg(not(target_os = "vita"))]
444            Self::CONT => "Signal::CONT".fmt(f),
445            #[cfg(not(target_os = "vita"))]
446            Self::STOP => "Signal::STOP".fmt(f),
447            #[cfg(not(target_os = "vita"))]
448            Self::TSTP => "Signal::TSTP".fmt(f),
449            #[cfg(not(target_os = "vita"))]
450            Self::TTIN => "Signal::TTIN".fmt(f),
451            #[cfg(not(target_os = "vita"))]
452            Self::TTOU => "Signal::TTOU".fmt(f),
453            #[cfg(not(target_os = "vita"))]
454            Self::URG => "Signal::URG".fmt(f),
455            #[cfg(not(target_os = "vita"))]
456            Self::XCPU => "Signal::XCPU".fmt(f),
457            #[cfg(not(target_os = "vita"))]
458            Self::XFSZ => "Signal::XFSZ".fmt(f),
459            #[cfg(not(target_os = "vita"))]
460            Self::VTALARM => "Signal::VTALARM".fmt(f),
461            #[cfg(not(target_os = "vita"))]
462            Self::PROF => "Signal::PROF".fmt(f),
463            #[cfg(not(target_os = "vita"))]
464            Self::WINCH => "Signal::WINCH".fmt(f),
465            #[cfg(not(any(target_os = "haiku", target_os = "vita")))]
466            Self::IO => "Signal::IO".fmt(f),
467            #[cfg(not(any(
468                bsd,
469                target_os = "haiku",
470                target_os = "horizon",
471                target_os = "hurd",
472                target_os = "vita"
473            )))]
474            Self::POWER => "Signal::POWER".fmt(f),
475            Self::SYS => "Signal::SYS".fmt(f),
476            #[cfg(any(
477                bsd,
478                solarish,
479                target_os = "aix",
480                target_os = "hermit",
481                all(
482                    linux_kernel,
483                    any(
484                        target_arch = "mips",
485                        target_arch = "mips32r6",
486                        target_arch = "mips64",
487                        target_arch = "mips64r6",
488                        target_arch = "sparc",
489                        target_arch = "sparc64"
490                    )
491                )
492            ))]
493            Self::EMT => "Signal::EMT".fmt(f),
494            #[cfg(bsd)]
495            Self::INFO => "Signal::INFO".fmt(f),
496            #[cfg(target_os = "freebsd")]
497            Self::THR => "Signal::THR".fmt(f),
498            #[cfg(target_os = "freebsd")]
499            Self::LIBRT => "Signal::LIBRT".fmt(f),
500
501            n => {
502                "Signal::from_raw(".fmt(f)?;
503                n.as_raw().fmt(f)?;
504                ")".fmt(f)
505            }
506        }
507    }
508}
509
510#[cfg(test)]
511mod tests {
512    use super::*;
513
514    #[test]
515    fn test_basics() {
516        assert_eq!(Signal::HUP.as_raw(), libc::SIGHUP);
517        unsafe {
518            assert_eq!(Signal::from_raw_unchecked(libc::SIGHUP), Signal::HUP);
519            assert_eq!(
520                Signal::from_raw_nonzero_unchecked(NonZeroI32::new(libc::SIGHUP).unwrap()),
521                Signal::HUP
522            );
523        }
524    }
525
526    #[test]
527    fn test_named() {
528        assert_eq!(Signal::from_named_raw(-1), None);
529        assert_eq!(Signal::from_named_raw(0), None);
530        assert_eq!(Signal::from_named_raw(c::SIGHUP), Some(Signal::HUP));
531        assert_eq!(Signal::from_named_raw(c::SIGSEGV), Some(Signal::SEGV));
532        assert_eq!(Signal::from_named_raw(c::SIGSYS), Some(Signal::SYS));
533        #[cfg(any(linux_like, solarish, target_os = "hurd"))]
534        {
535            assert_eq!(Signal::from_named_raw(libc::SIGRTMIN()), None);
536            assert_eq!(Signal::from_named_raw(libc::SIGRTMAX()), None);
537        }
538    }
539}