13da5c369Sopenharmony_ci// Portions of this file are Copyright 2014 The Rust Project Developers.
23da5c369Sopenharmony_ci// See https://www.rust-lang.org/policies/licenses.
33da5c369Sopenharmony_ci
43da5c369Sopenharmony_ci//! Operating system signals.
53da5c369Sopenharmony_ci
63da5c369Sopenharmony_ciuse crate::errno::Errno;
73da5c369Sopenharmony_ciuse crate::{Error, Result};
83da5c369Sopenharmony_ciuse cfg_if::cfg_if;
93da5c369Sopenharmony_ciuse std::fmt;
103da5c369Sopenharmony_ciuse std::mem;
113da5c369Sopenharmony_ci#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
123da5c369Sopenharmony_ciuse std::os::unix::io::RawFd;
133da5c369Sopenharmony_ciuse std::ptr;
143da5c369Sopenharmony_ciuse std::str::FromStr;
153da5c369Sopenharmony_ci
163da5c369Sopenharmony_ci#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
173da5c369Sopenharmony_ci#[cfg(any(feature = "aio", feature = "signal"))]
183da5c369Sopenharmony_cipub use self::sigevent::*;
193da5c369Sopenharmony_ci
203da5c369Sopenharmony_ci#[cfg(any(feature = "aio", feature = "process", feature = "signal"))]
213da5c369Sopenharmony_cilibc_enum! {
223da5c369Sopenharmony_ci    /// Types of operating system signals
233da5c369Sopenharmony_ci    // Currently there is only one definition of c_int in libc, as well as only one
243da5c369Sopenharmony_ci    // type for signal constants.
253da5c369Sopenharmony_ci    // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
263da5c369Sopenharmony_ci    // this is not (yet) possible.
273da5c369Sopenharmony_ci    #[repr(i32)]
283da5c369Sopenharmony_ci    #[non_exhaustive]
293da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(any(feature = "aio", feature = "signal"))))]
303da5c369Sopenharmony_ci    pub enum Signal {
313da5c369Sopenharmony_ci        /// Hangup
323da5c369Sopenharmony_ci        SIGHUP,
333da5c369Sopenharmony_ci        /// Interrupt
343da5c369Sopenharmony_ci        SIGINT,
353da5c369Sopenharmony_ci        /// Quit
363da5c369Sopenharmony_ci        SIGQUIT,
373da5c369Sopenharmony_ci        /// Illegal instruction (not reset when caught)
383da5c369Sopenharmony_ci        SIGILL,
393da5c369Sopenharmony_ci        /// Trace trap (not reset when caught)
403da5c369Sopenharmony_ci        SIGTRAP,
413da5c369Sopenharmony_ci        /// Abort
423da5c369Sopenharmony_ci        SIGABRT,
433da5c369Sopenharmony_ci        /// Bus error
443da5c369Sopenharmony_ci        SIGBUS,
453da5c369Sopenharmony_ci        /// Floating point exception
463da5c369Sopenharmony_ci        SIGFPE,
473da5c369Sopenharmony_ci        /// Kill (cannot be caught or ignored)
483da5c369Sopenharmony_ci        SIGKILL,
493da5c369Sopenharmony_ci        /// User defined signal 1
503da5c369Sopenharmony_ci        SIGUSR1,
513da5c369Sopenharmony_ci        /// Segmentation violation
523da5c369Sopenharmony_ci        SIGSEGV,
533da5c369Sopenharmony_ci        /// User defined signal 2
543da5c369Sopenharmony_ci        SIGUSR2,
553da5c369Sopenharmony_ci        /// Write on a pipe with no one to read it
563da5c369Sopenharmony_ci        SIGPIPE,
573da5c369Sopenharmony_ci        /// Alarm clock
583da5c369Sopenharmony_ci        SIGALRM,
593da5c369Sopenharmony_ci        /// Software termination signal from kill
603da5c369Sopenharmony_ci        SIGTERM,
613da5c369Sopenharmony_ci        /// Stack fault (obsolete)
623da5c369Sopenharmony_ci        #[cfg(all(any(target_os = "android", target_os = "emscripten",
633da5c369Sopenharmony_ci                      target_os = "fuchsia", target_os = "linux"),
643da5c369Sopenharmony_ci                  not(any(target_arch = "mips", target_arch = "mips64",
653da5c369Sopenharmony_ci                          target_arch = "sparc64"))))]
663da5c369Sopenharmony_ci        SIGSTKFLT,
673da5c369Sopenharmony_ci        /// To parent on child stop or exit
683da5c369Sopenharmony_ci        SIGCHLD,
693da5c369Sopenharmony_ci        /// Continue a stopped process
703da5c369Sopenharmony_ci        SIGCONT,
713da5c369Sopenharmony_ci        /// Sendable stop signal not from tty
723da5c369Sopenharmony_ci        SIGSTOP,
733da5c369Sopenharmony_ci        /// Stop signal from tty
743da5c369Sopenharmony_ci        SIGTSTP,
753da5c369Sopenharmony_ci        /// To readers pgrp upon background tty read
763da5c369Sopenharmony_ci        SIGTTIN,
773da5c369Sopenharmony_ci        /// Like TTIN if (tp->t_local&LTOSTOP)
783da5c369Sopenharmony_ci        SIGTTOU,
793da5c369Sopenharmony_ci        /// Urgent condition on IO channel
803da5c369Sopenharmony_ci        SIGURG,
813da5c369Sopenharmony_ci        /// Exceeded CPU time limit
823da5c369Sopenharmony_ci        SIGXCPU,
833da5c369Sopenharmony_ci        /// Exceeded file size limit
843da5c369Sopenharmony_ci        SIGXFSZ,
853da5c369Sopenharmony_ci        /// Virtual time alarm
863da5c369Sopenharmony_ci        SIGVTALRM,
873da5c369Sopenharmony_ci        /// Profiling time alarm
883da5c369Sopenharmony_ci        SIGPROF,
893da5c369Sopenharmony_ci        /// Window size changes
903da5c369Sopenharmony_ci        SIGWINCH,
913da5c369Sopenharmony_ci        /// Input/output possible signal
923da5c369Sopenharmony_ci        #[cfg(not(target_os = "haiku"))]
933da5c369Sopenharmony_ci        #[cfg_attr(docsrs, doc(cfg(all())))]
943da5c369Sopenharmony_ci        SIGIO,
953da5c369Sopenharmony_ci        #[cfg(any(target_os = "android", target_os = "emscripten",
963da5c369Sopenharmony_ci                  target_os = "fuchsia", target_os = "linux"))]
973da5c369Sopenharmony_ci        #[cfg_attr(docsrs, doc(cfg(all())))]
983da5c369Sopenharmony_ci        /// Power failure imminent.
993da5c369Sopenharmony_ci        SIGPWR,
1003da5c369Sopenharmony_ci        /// Bad system call
1013da5c369Sopenharmony_ci        SIGSYS,
1023da5c369Sopenharmony_ci        #[cfg(not(any(target_os = "android", target_os = "emscripten",
1033da5c369Sopenharmony_ci                      target_os = "fuchsia", target_os = "linux",
1043da5c369Sopenharmony_ci                      target_os = "redox", target_os = "haiku")))]
1053da5c369Sopenharmony_ci        #[cfg_attr(docsrs, doc(cfg(all())))]
1063da5c369Sopenharmony_ci        /// Emulator trap
1073da5c369Sopenharmony_ci        SIGEMT,
1083da5c369Sopenharmony_ci        #[cfg(not(any(target_os = "android", target_os = "emscripten",
1093da5c369Sopenharmony_ci                      target_os = "fuchsia", target_os = "linux",
1103da5c369Sopenharmony_ci                      target_os = "redox", target_os = "haiku")))]
1113da5c369Sopenharmony_ci        #[cfg_attr(docsrs, doc(cfg(all())))]
1123da5c369Sopenharmony_ci        /// Information request
1133da5c369Sopenharmony_ci        SIGINFO,
1143da5c369Sopenharmony_ci    }
1153da5c369Sopenharmony_ci    impl TryFrom<i32>
1163da5c369Sopenharmony_ci}
1173da5c369Sopenharmony_ci
1183da5c369Sopenharmony_ci#[cfg(feature = "signal")]
1193da5c369Sopenharmony_ciimpl FromStr for Signal {
1203da5c369Sopenharmony_ci    type Err = Error;
1213da5c369Sopenharmony_ci    fn from_str(s: &str) -> Result<Signal> {
1223da5c369Sopenharmony_ci        Ok(match s {
1233da5c369Sopenharmony_ci            "SIGHUP" => Signal::SIGHUP,
1243da5c369Sopenharmony_ci            "SIGINT" => Signal::SIGINT,
1253da5c369Sopenharmony_ci            "SIGQUIT" => Signal::SIGQUIT,
1263da5c369Sopenharmony_ci            "SIGILL" => Signal::SIGILL,
1273da5c369Sopenharmony_ci            "SIGTRAP" => Signal::SIGTRAP,
1283da5c369Sopenharmony_ci            "SIGABRT" => Signal::SIGABRT,
1293da5c369Sopenharmony_ci            "SIGBUS" => Signal::SIGBUS,
1303da5c369Sopenharmony_ci            "SIGFPE" => Signal::SIGFPE,
1313da5c369Sopenharmony_ci            "SIGKILL" => Signal::SIGKILL,
1323da5c369Sopenharmony_ci            "SIGUSR1" => Signal::SIGUSR1,
1333da5c369Sopenharmony_ci            "SIGSEGV" => Signal::SIGSEGV,
1343da5c369Sopenharmony_ci            "SIGUSR2" => Signal::SIGUSR2,
1353da5c369Sopenharmony_ci            "SIGPIPE" => Signal::SIGPIPE,
1363da5c369Sopenharmony_ci            "SIGALRM" => Signal::SIGALRM,
1373da5c369Sopenharmony_ci            "SIGTERM" => Signal::SIGTERM,
1383da5c369Sopenharmony_ci            #[cfg(all(
1393da5c369Sopenharmony_ci                any(
1403da5c369Sopenharmony_ci                    target_os = "android",
1413da5c369Sopenharmony_ci                    target_os = "emscripten",
1423da5c369Sopenharmony_ci                    target_os = "fuchsia",
1433da5c369Sopenharmony_ci                    target_os = "linux"
1443da5c369Sopenharmony_ci                ),
1453da5c369Sopenharmony_ci                not(any(
1463da5c369Sopenharmony_ci                    target_arch = "mips",
1473da5c369Sopenharmony_ci                    target_arch = "mips64",
1483da5c369Sopenharmony_ci                    target_arch = "sparc64"
1493da5c369Sopenharmony_ci                ))
1503da5c369Sopenharmony_ci            ))]
1513da5c369Sopenharmony_ci            "SIGSTKFLT" => Signal::SIGSTKFLT,
1523da5c369Sopenharmony_ci            "SIGCHLD" => Signal::SIGCHLD,
1533da5c369Sopenharmony_ci            "SIGCONT" => Signal::SIGCONT,
1543da5c369Sopenharmony_ci            "SIGSTOP" => Signal::SIGSTOP,
1553da5c369Sopenharmony_ci            "SIGTSTP" => Signal::SIGTSTP,
1563da5c369Sopenharmony_ci            "SIGTTIN" => Signal::SIGTTIN,
1573da5c369Sopenharmony_ci            "SIGTTOU" => Signal::SIGTTOU,
1583da5c369Sopenharmony_ci            "SIGURG" => Signal::SIGURG,
1593da5c369Sopenharmony_ci            "SIGXCPU" => Signal::SIGXCPU,
1603da5c369Sopenharmony_ci            "SIGXFSZ" => Signal::SIGXFSZ,
1613da5c369Sopenharmony_ci            "SIGVTALRM" => Signal::SIGVTALRM,
1623da5c369Sopenharmony_ci            "SIGPROF" => Signal::SIGPROF,
1633da5c369Sopenharmony_ci            "SIGWINCH" => Signal::SIGWINCH,
1643da5c369Sopenharmony_ci            #[cfg(not(target_os = "haiku"))]
1653da5c369Sopenharmony_ci            "SIGIO" => Signal::SIGIO,
1663da5c369Sopenharmony_ci            #[cfg(any(
1673da5c369Sopenharmony_ci                target_os = "android",
1683da5c369Sopenharmony_ci                target_os = "emscripten",
1693da5c369Sopenharmony_ci                target_os = "fuchsia",
1703da5c369Sopenharmony_ci                target_os = "linux"
1713da5c369Sopenharmony_ci            ))]
1723da5c369Sopenharmony_ci            "SIGPWR" => Signal::SIGPWR,
1733da5c369Sopenharmony_ci            "SIGSYS" => Signal::SIGSYS,
1743da5c369Sopenharmony_ci            #[cfg(not(any(
1753da5c369Sopenharmony_ci                target_os = "android",
1763da5c369Sopenharmony_ci                target_os = "emscripten",
1773da5c369Sopenharmony_ci                target_os = "fuchsia",
1783da5c369Sopenharmony_ci                target_os = "linux",
1793da5c369Sopenharmony_ci                target_os = "redox",
1803da5c369Sopenharmony_ci                target_os = "haiku"
1813da5c369Sopenharmony_ci            )))]
1823da5c369Sopenharmony_ci            "SIGEMT" => Signal::SIGEMT,
1833da5c369Sopenharmony_ci            #[cfg(not(any(
1843da5c369Sopenharmony_ci                target_os = "android",
1853da5c369Sopenharmony_ci                target_os = "emscripten",
1863da5c369Sopenharmony_ci                target_os = "fuchsia",
1873da5c369Sopenharmony_ci                target_os = "linux",
1883da5c369Sopenharmony_ci                target_os = "redox",
1893da5c369Sopenharmony_ci                target_os = "haiku"
1903da5c369Sopenharmony_ci            )))]
1913da5c369Sopenharmony_ci            "SIGINFO" => Signal::SIGINFO,
1923da5c369Sopenharmony_ci            _ => return Err(Errno::EINVAL),
1933da5c369Sopenharmony_ci        })
1943da5c369Sopenharmony_ci    }
1953da5c369Sopenharmony_ci}
1963da5c369Sopenharmony_ci
1973da5c369Sopenharmony_ci#[cfg(feature = "signal")]
1983da5c369Sopenharmony_ciimpl Signal {
1993da5c369Sopenharmony_ci    /// Returns name of signal.
2003da5c369Sopenharmony_ci    ///
2013da5c369Sopenharmony_ci    /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
2023da5c369Sopenharmony_ci    /// with difference that returned string is `'static`
2033da5c369Sopenharmony_ci    /// and not bound to `self`'s lifetime.
2043da5c369Sopenharmony_ci    pub const fn as_str(self) -> &'static str {
2053da5c369Sopenharmony_ci        match self {
2063da5c369Sopenharmony_ci            Signal::SIGHUP => "SIGHUP",
2073da5c369Sopenharmony_ci            Signal::SIGINT => "SIGINT",
2083da5c369Sopenharmony_ci            Signal::SIGQUIT => "SIGQUIT",
2093da5c369Sopenharmony_ci            Signal::SIGILL => "SIGILL",
2103da5c369Sopenharmony_ci            Signal::SIGTRAP => "SIGTRAP",
2113da5c369Sopenharmony_ci            Signal::SIGABRT => "SIGABRT",
2123da5c369Sopenharmony_ci            Signal::SIGBUS => "SIGBUS",
2133da5c369Sopenharmony_ci            Signal::SIGFPE => "SIGFPE",
2143da5c369Sopenharmony_ci            Signal::SIGKILL => "SIGKILL",
2153da5c369Sopenharmony_ci            Signal::SIGUSR1 => "SIGUSR1",
2163da5c369Sopenharmony_ci            Signal::SIGSEGV => "SIGSEGV",
2173da5c369Sopenharmony_ci            Signal::SIGUSR2 => "SIGUSR2",
2183da5c369Sopenharmony_ci            Signal::SIGPIPE => "SIGPIPE",
2193da5c369Sopenharmony_ci            Signal::SIGALRM => "SIGALRM",
2203da5c369Sopenharmony_ci            Signal::SIGTERM => "SIGTERM",
2213da5c369Sopenharmony_ci            #[cfg(all(
2223da5c369Sopenharmony_ci                any(
2233da5c369Sopenharmony_ci                    target_os = "android",
2243da5c369Sopenharmony_ci                    target_os = "emscripten",
2253da5c369Sopenharmony_ci                    target_os = "fuchsia",
2263da5c369Sopenharmony_ci                    target_os = "linux"
2273da5c369Sopenharmony_ci                ),
2283da5c369Sopenharmony_ci                not(any(
2293da5c369Sopenharmony_ci                    target_arch = "mips",
2303da5c369Sopenharmony_ci                    target_arch = "mips64",
2313da5c369Sopenharmony_ci                    target_arch = "sparc64"
2323da5c369Sopenharmony_ci                ))
2333da5c369Sopenharmony_ci            ))]
2343da5c369Sopenharmony_ci            Signal::SIGSTKFLT => "SIGSTKFLT",
2353da5c369Sopenharmony_ci            Signal::SIGCHLD => "SIGCHLD",
2363da5c369Sopenharmony_ci            Signal::SIGCONT => "SIGCONT",
2373da5c369Sopenharmony_ci            Signal::SIGSTOP => "SIGSTOP",
2383da5c369Sopenharmony_ci            Signal::SIGTSTP => "SIGTSTP",
2393da5c369Sopenharmony_ci            Signal::SIGTTIN => "SIGTTIN",
2403da5c369Sopenharmony_ci            Signal::SIGTTOU => "SIGTTOU",
2413da5c369Sopenharmony_ci            Signal::SIGURG => "SIGURG",
2423da5c369Sopenharmony_ci            Signal::SIGXCPU => "SIGXCPU",
2433da5c369Sopenharmony_ci            Signal::SIGXFSZ => "SIGXFSZ",
2443da5c369Sopenharmony_ci            Signal::SIGVTALRM => "SIGVTALRM",
2453da5c369Sopenharmony_ci            Signal::SIGPROF => "SIGPROF",
2463da5c369Sopenharmony_ci            Signal::SIGWINCH => "SIGWINCH",
2473da5c369Sopenharmony_ci            #[cfg(not(target_os = "haiku"))]
2483da5c369Sopenharmony_ci            Signal::SIGIO => "SIGIO",
2493da5c369Sopenharmony_ci            #[cfg(any(
2503da5c369Sopenharmony_ci                target_os = "android",
2513da5c369Sopenharmony_ci                target_os = "emscripten",
2523da5c369Sopenharmony_ci                target_os = "fuchsia",
2533da5c369Sopenharmony_ci                target_os = "linux"
2543da5c369Sopenharmony_ci            ))]
2553da5c369Sopenharmony_ci            Signal::SIGPWR => "SIGPWR",
2563da5c369Sopenharmony_ci            Signal::SIGSYS => "SIGSYS",
2573da5c369Sopenharmony_ci            #[cfg(not(any(
2583da5c369Sopenharmony_ci                target_os = "android",
2593da5c369Sopenharmony_ci                target_os = "emscripten",
2603da5c369Sopenharmony_ci                target_os = "fuchsia",
2613da5c369Sopenharmony_ci                target_os = "linux",
2623da5c369Sopenharmony_ci                target_os = "redox",
2633da5c369Sopenharmony_ci                target_os = "haiku"
2643da5c369Sopenharmony_ci            )))]
2653da5c369Sopenharmony_ci            Signal::SIGEMT => "SIGEMT",
2663da5c369Sopenharmony_ci            #[cfg(not(any(
2673da5c369Sopenharmony_ci                target_os = "android",
2683da5c369Sopenharmony_ci                target_os = "emscripten",
2693da5c369Sopenharmony_ci                target_os = "fuchsia",
2703da5c369Sopenharmony_ci                target_os = "linux",
2713da5c369Sopenharmony_ci                target_os = "redox",
2723da5c369Sopenharmony_ci                target_os = "haiku"
2733da5c369Sopenharmony_ci            )))]
2743da5c369Sopenharmony_ci            Signal::SIGINFO => "SIGINFO",
2753da5c369Sopenharmony_ci        }
2763da5c369Sopenharmony_ci    }
2773da5c369Sopenharmony_ci}
2783da5c369Sopenharmony_ci
2793da5c369Sopenharmony_ci#[cfg(feature = "signal")]
2803da5c369Sopenharmony_ciimpl AsRef<str> for Signal {
2813da5c369Sopenharmony_ci    fn as_ref(&self) -> &str {
2823da5c369Sopenharmony_ci        self.as_str()
2833da5c369Sopenharmony_ci    }
2843da5c369Sopenharmony_ci}
2853da5c369Sopenharmony_ci
2863da5c369Sopenharmony_ci#[cfg(feature = "signal")]
2873da5c369Sopenharmony_ciimpl fmt::Display for Signal {
2883da5c369Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2893da5c369Sopenharmony_ci        f.write_str(self.as_ref())
2903da5c369Sopenharmony_ci    }
2913da5c369Sopenharmony_ci}
2923da5c369Sopenharmony_ci
2933da5c369Sopenharmony_ci#[cfg(feature = "signal")]
2943da5c369Sopenharmony_cipub use self::Signal::*;
2953da5c369Sopenharmony_ci
2963da5c369Sopenharmony_ci#[cfg(target_os = "redox")]
2973da5c369Sopenharmony_ci#[cfg(feature = "signal")]
2983da5c369Sopenharmony_ciconst SIGNALS: [Signal; 29] = [
2993da5c369Sopenharmony_ci    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
3003da5c369Sopenharmony_ci    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
3013da5c369Sopenharmony_ci    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
3023da5c369Sopenharmony_ci    SIGPROF, SIGWINCH, SIGIO, SIGSYS,
3033da5c369Sopenharmony_ci];
3043da5c369Sopenharmony_ci#[cfg(target_os = "haiku")]
3053da5c369Sopenharmony_ci#[cfg(feature = "signal")]
3063da5c369Sopenharmony_ciconst SIGNALS: [Signal; 28] = [
3073da5c369Sopenharmony_ci    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
3083da5c369Sopenharmony_ci    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
3093da5c369Sopenharmony_ci    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
3103da5c369Sopenharmony_ci    SIGPROF, SIGWINCH, SIGSYS,
3113da5c369Sopenharmony_ci];
3123da5c369Sopenharmony_ci#[cfg(all(
3133da5c369Sopenharmony_ci    any(
3143da5c369Sopenharmony_ci        target_os = "linux",
3153da5c369Sopenharmony_ci        target_os = "android",
3163da5c369Sopenharmony_ci        target_os = "emscripten",
3173da5c369Sopenharmony_ci        target_os = "fuchsia"
3183da5c369Sopenharmony_ci    ),
3193da5c369Sopenharmony_ci    not(any(
3203da5c369Sopenharmony_ci        target_arch = "mips",
3213da5c369Sopenharmony_ci        target_arch = "mips64",
3223da5c369Sopenharmony_ci        target_arch = "sparc64"
3233da5c369Sopenharmony_ci    ))
3243da5c369Sopenharmony_ci))]
3253da5c369Sopenharmony_ci#[cfg(feature = "signal")]
3263da5c369Sopenharmony_ciconst SIGNALS: [Signal; 31] = [
3273da5c369Sopenharmony_ci    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
3283da5c369Sopenharmony_ci    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGSTKFLT, SIGCHLD,
3293da5c369Sopenharmony_ci    SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ,
3303da5c369Sopenharmony_ci    SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
3313da5c369Sopenharmony_ci];
3323da5c369Sopenharmony_ci#[cfg(all(
3333da5c369Sopenharmony_ci    any(
3343da5c369Sopenharmony_ci        target_os = "linux",
3353da5c369Sopenharmony_ci        target_os = "android",
3363da5c369Sopenharmony_ci        target_os = "emscripten",
3373da5c369Sopenharmony_ci        target_os = "fuchsia"
3383da5c369Sopenharmony_ci    ),
3393da5c369Sopenharmony_ci    any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")
3403da5c369Sopenharmony_ci))]
3413da5c369Sopenharmony_ci#[cfg(feature = "signal")]
3423da5c369Sopenharmony_ciconst SIGNALS: [Signal; 30] = [
3433da5c369Sopenharmony_ci    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
3443da5c369Sopenharmony_ci    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
3453da5c369Sopenharmony_ci    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
3463da5c369Sopenharmony_ci    SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
3473da5c369Sopenharmony_ci];
3483da5c369Sopenharmony_ci#[cfg(not(any(
3493da5c369Sopenharmony_ci    target_os = "linux",
3503da5c369Sopenharmony_ci    target_os = "android",
3513da5c369Sopenharmony_ci    target_os = "fuchsia",
3523da5c369Sopenharmony_ci    target_os = "emscripten",
3533da5c369Sopenharmony_ci    target_os = "redox",
3543da5c369Sopenharmony_ci    target_os = "haiku"
3553da5c369Sopenharmony_ci)))]
3563da5c369Sopenharmony_ci#[cfg(feature = "signal")]
3573da5c369Sopenharmony_ciconst SIGNALS: [Signal; 31] = [
3583da5c369Sopenharmony_ci    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
3593da5c369Sopenharmony_ci    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
3603da5c369Sopenharmony_ci    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
3613da5c369Sopenharmony_ci    SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT, SIGINFO,
3623da5c369Sopenharmony_ci];
3633da5c369Sopenharmony_ci
3643da5c369Sopenharmony_cifeature! {
3653da5c369Sopenharmony_ci#![feature = "signal"]
3663da5c369Sopenharmony_ci
3673da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
3683da5c369Sopenharmony_ci/// Iterate through all signals defined by this operating system
3693da5c369Sopenharmony_cipub struct SignalIterator {
3703da5c369Sopenharmony_ci    next: usize,
3713da5c369Sopenharmony_ci}
3723da5c369Sopenharmony_ci
3733da5c369Sopenharmony_ciimpl Iterator for SignalIterator {
3743da5c369Sopenharmony_ci    type Item = Signal;
3753da5c369Sopenharmony_ci
3763da5c369Sopenharmony_ci    fn next(&mut self) -> Option<Signal> {
3773da5c369Sopenharmony_ci        if self.next < SIGNALS.len() {
3783da5c369Sopenharmony_ci            let next_signal = SIGNALS[self.next];
3793da5c369Sopenharmony_ci            self.next += 1;
3803da5c369Sopenharmony_ci            Some(next_signal)
3813da5c369Sopenharmony_ci        } else {
3823da5c369Sopenharmony_ci            None
3833da5c369Sopenharmony_ci        }
3843da5c369Sopenharmony_ci    }
3853da5c369Sopenharmony_ci}
3863da5c369Sopenharmony_ci
3873da5c369Sopenharmony_ciimpl Signal {
3883da5c369Sopenharmony_ci    /// Iterate through all signals defined by this OS
3893da5c369Sopenharmony_ci    pub const fn iterator() -> SignalIterator {
3903da5c369Sopenharmony_ci        SignalIterator{next: 0}
3913da5c369Sopenharmony_ci    }
3923da5c369Sopenharmony_ci}
3933da5c369Sopenharmony_ci
3943da5c369Sopenharmony_ci/// Alias for [`SIGABRT`]
3953da5c369Sopenharmony_cipub const SIGIOT : Signal = SIGABRT;
3963da5c369Sopenharmony_ci/// Alias for [`SIGIO`]
3973da5c369Sopenharmony_ci#[cfg(not(target_os = "haiku"))]
3983da5c369Sopenharmony_cipub const SIGPOLL : Signal = SIGIO;
3993da5c369Sopenharmony_ci/// Alias for [`SIGSYS`]
4003da5c369Sopenharmony_cipub const SIGUNUSED : Signal = SIGSYS;
4013da5c369Sopenharmony_ci
4023da5c369Sopenharmony_cicfg_if! {
4033da5c369Sopenharmony_ci    if #[cfg(target_os = "redox")] {
4043da5c369Sopenharmony_ci        type SaFlags_t = libc::c_ulong;
4053da5c369Sopenharmony_ci    } else if #[cfg(target_env = "uclibc")] {
4063da5c369Sopenharmony_ci        type SaFlags_t = libc::c_ulong;
4073da5c369Sopenharmony_ci    } else {
4083da5c369Sopenharmony_ci        type SaFlags_t = libc::c_int;
4093da5c369Sopenharmony_ci    }
4103da5c369Sopenharmony_ci}
4113da5c369Sopenharmony_ci}
4123da5c369Sopenharmony_ci
4133da5c369Sopenharmony_ci#[cfg(feature = "signal")]
4143da5c369Sopenharmony_cilibc_bitflags! {
4153da5c369Sopenharmony_ci    /// Controls the behavior of a [`SigAction`]
4163da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
4173da5c369Sopenharmony_ci    pub struct SaFlags: SaFlags_t {
4183da5c369Sopenharmony_ci        /// When catching a [`Signal::SIGCHLD`] signal, the signal will be
4193da5c369Sopenharmony_ci        /// generated only when a child process exits, not when a child process
4203da5c369Sopenharmony_ci        /// stops.
4213da5c369Sopenharmony_ci        SA_NOCLDSTOP;
4223da5c369Sopenharmony_ci        /// When catching a [`Signal::SIGCHLD`] signal, the system will not
4233da5c369Sopenharmony_ci        /// create zombie processes when children of the calling process exit.
4243da5c369Sopenharmony_ci        SA_NOCLDWAIT;
4253da5c369Sopenharmony_ci        /// Further occurrences of the delivered signal are not masked during
4263da5c369Sopenharmony_ci        /// the execution of the handler.
4273da5c369Sopenharmony_ci        SA_NODEFER;
4283da5c369Sopenharmony_ci        /// The system will deliver the signal to the process on a signal stack,
4293da5c369Sopenharmony_ci        /// specified by each thread with sigaltstack(2).
4303da5c369Sopenharmony_ci        SA_ONSTACK;
4313da5c369Sopenharmony_ci        /// The handler is reset back to the default at the moment the signal is
4323da5c369Sopenharmony_ci        /// delivered.
4333da5c369Sopenharmony_ci        SA_RESETHAND;
4343da5c369Sopenharmony_ci        /// Requests that certain system calls restart if interrupted by this
4353da5c369Sopenharmony_ci        /// signal.  See the man page for complete details.
4363da5c369Sopenharmony_ci        SA_RESTART;
4373da5c369Sopenharmony_ci        /// This flag is controlled internally by Nix.
4383da5c369Sopenharmony_ci        SA_SIGINFO;
4393da5c369Sopenharmony_ci    }
4403da5c369Sopenharmony_ci}
4413da5c369Sopenharmony_ci
4423da5c369Sopenharmony_ci#[cfg(feature = "signal")]
4433da5c369Sopenharmony_cilibc_enum! {
4443da5c369Sopenharmony_ci    /// Specifies how certain functions should manipulate a signal mask
4453da5c369Sopenharmony_ci    #[repr(i32)]
4463da5c369Sopenharmony_ci    #[non_exhaustive]
4473da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
4483da5c369Sopenharmony_ci    pub enum SigmaskHow {
4493da5c369Sopenharmony_ci        /// The new mask is the union of the current mask and the specified set.
4503da5c369Sopenharmony_ci        SIG_BLOCK,
4513da5c369Sopenharmony_ci        /// The new mask is the intersection of the current mask and the
4523da5c369Sopenharmony_ci        /// complement of the specified set.
4533da5c369Sopenharmony_ci        SIG_UNBLOCK,
4543da5c369Sopenharmony_ci        /// The current mask is replaced by the specified set.
4553da5c369Sopenharmony_ci        SIG_SETMASK,
4563da5c369Sopenharmony_ci    }
4573da5c369Sopenharmony_ci}
4583da5c369Sopenharmony_ci
4593da5c369Sopenharmony_cifeature! {
4603da5c369Sopenharmony_ci#![feature = "signal"]
4613da5c369Sopenharmony_ci
4623da5c369Sopenharmony_ciuse crate::unistd::Pid;
4633da5c369Sopenharmony_ciuse std::iter::Extend;
4643da5c369Sopenharmony_ciuse std::iter::FromIterator;
4653da5c369Sopenharmony_ciuse std::iter::IntoIterator;
4663da5c369Sopenharmony_ci
4673da5c369Sopenharmony_ci/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
4683da5c369Sopenharmony_ci// We are using `transparent` here to be super sure that `SigSet`
4693da5c369Sopenharmony_ci// is represented exactly like the `sigset_t` struct from C.
4703da5c369Sopenharmony_ci#[repr(transparent)]
4713da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
4723da5c369Sopenharmony_cipub struct SigSet {
4733da5c369Sopenharmony_ci    sigset: libc::sigset_t
4743da5c369Sopenharmony_ci}
4753da5c369Sopenharmony_ci
4763da5c369Sopenharmony_ciimpl SigSet {
4773da5c369Sopenharmony_ci    /// Initialize to include all signals.
4783da5c369Sopenharmony_ci    #[doc(alias("sigfillset"))]
4793da5c369Sopenharmony_ci    pub fn all() -> SigSet {
4803da5c369Sopenharmony_ci        let mut sigset = mem::MaybeUninit::uninit();
4813da5c369Sopenharmony_ci        let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
4823da5c369Sopenharmony_ci
4833da5c369Sopenharmony_ci        unsafe{ SigSet { sigset: sigset.assume_init() } }
4843da5c369Sopenharmony_ci    }
4853da5c369Sopenharmony_ci
4863da5c369Sopenharmony_ci    /// Initialize to include nothing.
4873da5c369Sopenharmony_ci    #[doc(alias("sigemptyset"))]
4883da5c369Sopenharmony_ci    pub fn empty() -> SigSet {
4893da5c369Sopenharmony_ci        let mut sigset = mem::MaybeUninit::uninit();
4903da5c369Sopenharmony_ci        let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
4913da5c369Sopenharmony_ci
4923da5c369Sopenharmony_ci        unsafe{ SigSet { sigset: sigset.assume_init() } }
4933da5c369Sopenharmony_ci    }
4943da5c369Sopenharmony_ci
4953da5c369Sopenharmony_ci    /// Add the specified signal to the set.
4963da5c369Sopenharmony_ci    #[doc(alias("sigaddset"))]
4973da5c369Sopenharmony_ci    pub fn add(&mut self, signal: Signal) {
4983da5c369Sopenharmony_ci        unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
4993da5c369Sopenharmony_ci    }
5003da5c369Sopenharmony_ci
5013da5c369Sopenharmony_ci    /// Remove all signals from this set.
5023da5c369Sopenharmony_ci    #[doc(alias("sigemptyset"))]
5033da5c369Sopenharmony_ci    pub fn clear(&mut self) {
5043da5c369Sopenharmony_ci        unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
5053da5c369Sopenharmony_ci    }
5063da5c369Sopenharmony_ci
5073da5c369Sopenharmony_ci    /// Remove the specified signal from this set.
5083da5c369Sopenharmony_ci    #[doc(alias("sigdelset"))]
5093da5c369Sopenharmony_ci    pub fn remove(&mut self, signal: Signal) {
5103da5c369Sopenharmony_ci        unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
5113da5c369Sopenharmony_ci    }
5123da5c369Sopenharmony_ci
5133da5c369Sopenharmony_ci    /// Return whether this set includes the specified signal.
5143da5c369Sopenharmony_ci    #[doc(alias("sigismember"))]
5153da5c369Sopenharmony_ci    pub fn contains(&self, signal: Signal) -> bool {
5163da5c369Sopenharmony_ci        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
5173da5c369Sopenharmony_ci
5183da5c369Sopenharmony_ci        match res {
5193da5c369Sopenharmony_ci            1 => true,
5203da5c369Sopenharmony_ci            0 => false,
5213da5c369Sopenharmony_ci            _ => unreachable!("unexpected value from sigismember"),
5223da5c369Sopenharmony_ci        }
5233da5c369Sopenharmony_ci    }
5243da5c369Sopenharmony_ci
5253da5c369Sopenharmony_ci    /// Returns an iterator that yields the signals contained in this set.
5263da5c369Sopenharmony_ci    pub fn iter(&self) -> SigSetIter<'_> {
5273da5c369Sopenharmony_ci        self.into_iter()
5283da5c369Sopenharmony_ci    }
5293da5c369Sopenharmony_ci
5303da5c369Sopenharmony_ci    /// Gets the currently blocked (masked) set of signals for the calling thread.
5313da5c369Sopenharmony_ci    pub fn thread_get_mask() -> Result<SigSet> {
5323da5c369Sopenharmony_ci        let mut oldmask = mem::MaybeUninit::uninit();
5333da5c369Sopenharmony_ci        do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
5343da5c369Sopenharmony_ci        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
5353da5c369Sopenharmony_ci    }
5363da5c369Sopenharmony_ci
5373da5c369Sopenharmony_ci    /// Sets the set of signals as the signal mask for the calling thread.
5383da5c369Sopenharmony_ci    pub fn thread_set_mask(&self) -> Result<()> {
5393da5c369Sopenharmony_ci        pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
5403da5c369Sopenharmony_ci    }
5413da5c369Sopenharmony_ci
5423da5c369Sopenharmony_ci    /// Adds the set of signals to the signal mask for the calling thread.
5433da5c369Sopenharmony_ci    pub fn thread_block(&self) -> Result<()> {
5443da5c369Sopenharmony_ci        pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
5453da5c369Sopenharmony_ci    }
5463da5c369Sopenharmony_ci
5473da5c369Sopenharmony_ci    /// Removes the set of signals from the signal mask for the calling thread.
5483da5c369Sopenharmony_ci    pub fn thread_unblock(&self) -> Result<()> {
5493da5c369Sopenharmony_ci        pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
5503da5c369Sopenharmony_ci    }
5513da5c369Sopenharmony_ci
5523da5c369Sopenharmony_ci    /// Sets the set of signals as the signal mask, and returns the old mask.
5533da5c369Sopenharmony_ci    pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
5543da5c369Sopenharmony_ci        let mut oldmask = mem::MaybeUninit::uninit();
5553da5c369Sopenharmony_ci        do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
5563da5c369Sopenharmony_ci        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
5573da5c369Sopenharmony_ci    }
5583da5c369Sopenharmony_ci
5593da5c369Sopenharmony_ci    /// Suspends execution of the calling thread until one of the signals in the
5603da5c369Sopenharmony_ci    /// signal mask becomes pending, and returns the accepted signal.
5613da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
5623da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
5633da5c369Sopenharmony_ci    pub fn wait(&self) -> Result<Signal> {
5643da5c369Sopenharmony_ci        use std::convert::TryFrom;
5653da5c369Sopenharmony_ci
5663da5c369Sopenharmony_ci        let mut signum = mem::MaybeUninit::uninit();
5673da5c369Sopenharmony_ci        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
5683da5c369Sopenharmony_ci
5693da5c369Sopenharmony_ci        Errno::result(res).map(|_| unsafe {
5703da5c369Sopenharmony_ci            Signal::try_from(signum.assume_init()).unwrap()
5713da5c369Sopenharmony_ci        })
5723da5c369Sopenharmony_ci    }
5733da5c369Sopenharmony_ci
5743da5c369Sopenharmony_ci    /// Converts a `libc::sigset_t` object to a [`SigSet`] without checking  whether the
5753da5c369Sopenharmony_ci    /// `libc::sigset_t` is already initialized.
5763da5c369Sopenharmony_ci    ///
5773da5c369Sopenharmony_ci    /// # Safety
5783da5c369Sopenharmony_ci    ///
5793da5c369Sopenharmony_ci    /// The `sigset` passed in must be a valid an initialized `libc::sigset_t` by calling either
5803da5c369Sopenharmony_ci    /// [`sigemptyset(3)`](https://man7.org/linux/man-pages/man3/sigemptyset.3p.html) or
5813da5c369Sopenharmony_ci    /// [`sigfillset(3)`](https://man7.org/linux/man-pages/man3/sigfillset.3p.html).
5823da5c369Sopenharmony_ci    /// Otherwise, the results are undefined.
5833da5c369Sopenharmony_ci    pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet {
5843da5c369Sopenharmony_ci        SigSet { sigset }
5853da5c369Sopenharmony_ci    }
5863da5c369Sopenharmony_ci}
5873da5c369Sopenharmony_ci
5883da5c369Sopenharmony_ciimpl AsRef<libc::sigset_t> for SigSet {
5893da5c369Sopenharmony_ci    fn as_ref(&self) -> &libc::sigset_t {
5903da5c369Sopenharmony_ci        &self.sigset
5913da5c369Sopenharmony_ci    }
5923da5c369Sopenharmony_ci}
5933da5c369Sopenharmony_ci
5943da5c369Sopenharmony_ci// TODO: Consider specialization for the case where T is &SigSet and libc::sigorset is available.
5953da5c369Sopenharmony_ciimpl Extend<Signal> for SigSet {
5963da5c369Sopenharmony_ci    fn extend<T>(&mut self, iter: T)
5973da5c369Sopenharmony_ci    where T: IntoIterator<Item = Signal> {
5983da5c369Sopenharmony_ci        for signal in iter {
5993da5c369Sopenharmony_ci            self.add(signal);
6003da5c369Sopenharmony_ci        }
6013da5c369Sopenharmony_ci    }
6023da5c369Sopenharmony_ci}
6033da5c369Sopenharmony_ci
6043da5c369Sopenharmony_ciimpl FromIterator<Signal> for SigSet {
6053da5c369Sopenharmony_ci    fn from_iter<T>(iter: T) -> Self
6063da5c369Sopenharmony_ci    where T: IntoIterator<Item = Signal> {
6073da5c369Sopenharmony_ci        let mut sigset = SigSet::empty();
6083da5c369Sopenharmony_ci        sigset.extend(iter);
6093da5c369Sopenharmony_ci        sigset
6103da5c369Sopenharmony_ci    }
6113da5c369Sopenharmony_ci}
6123da5c369Sopenharmony_ci
6133da5c369Sopenharmony_ci/// Iterator for a [`SigSet`].
6143da5c369Sopenharmony_ci///
6153da5c369Sopenharmony_ci/// Call [`SigSet::iter`] to create an iterator.
6163da5c369Sopenharmony_ci#[derive(Clone, Debug)]
6173da5c369Sopenharmony_cipub struct SigSetIter<'a> {
6183da5c369Sopenharmony_ci    sigset: &'a SigSet,
6193da5c369Sopenharmony_ci    inner: SignalIterator,
6203da5c369Sopenharmony_ci}
6213da5c369Sopenharmony_ci
6223da5c369Sopenharmony_ciimpl Iterator for SigSetIter<'_> {
6233da5c369Sopenharmony_ci    type Item = Signal;
6243da5c369Sopenharmony_ci    fn next(&mut self) -> Option<Signal> {
6253da5c369Sopenharmony_ci        loop {
6263da5c369Sopenharmony_ci            match self.inner.next() {
6273da5c369Sopenharmony_ci                None => return None,
6283da5c369Sopenharmony_ci                Some(signal) if self.sigset.contains(signal) => return Some(signal),
6293da5c369Sopenharmony_ci                Some(_signal) => continue,
6303da5c369Sopenharmony_ci            }
6313da5c369Sopenharmony_ci        }
6323da5c369Sopenharmony_ci    }
6333da5c369Sopenharmony_ci}
6343da5c369Sopenharmony_ci
6353da5c369Sopenharmony_ciimpl<'a> IntoIterator for &'a SigSet {
6363da5c369Sopenharmony_ci    type Item = Signal;
6373da5c369Sopenharmony_ci    type IntoIter = SigSetIter<'a>;
6383da5c369Sopenharmony_ci    fn into_iter(self) -> Self::IntoIter {
6393da5c369Sopenharmony_ci        SigSetIter { sigset: self, inner: Signal::iterator() }
6403da5c369Sopenharmony_ci    }
6413da5c369Sopenharmony_ci}
6423da5c369Sopenharmony_ci
6433da5c369Sopenharmony_ci/// A signal handler.
6443da5c369Sopenharmony_ci#[allow(unknown_lints)]
6453da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
6463da5c369Sopenharmony_cipub enum SigHandler {
6473da5c369Sopenharmony_ci    /// Default signal handling.
6483da5c369Sopenharmony_ci    SigDfl,
6493da5c369Sopenharmony_ci    /// Request that the signal be ignored.
6503da5c369Sopenharmony_ci    SigIgn,
6513da5c369Sopenharmony_ci    /// Use the given signal-catching function, which takes in the signal.
6523da5c369Sopenharmony_ci    Handler(extern fn(libc::c_int)),
6533da5c369Sopenharmony_ci    /// Use the given signal-catching function, which takes in the signal, information about how
6543da5c369Sopenharmony_ci    /// the signal was generated, and a pointer to the threads `ucontext_t`.
6553da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
6563da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
6573da5c369Sopenharmony_ci    SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
6583da5c369Sopenharmony_ci}
6593da5c369Sopenharmony_ci
6603da5c369Sopenharmony_ci/// Action to take on receipt of a signal. Corresponds to `sigaction`.
6613da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
6623da5c369Sopenharmony_cipub struct SigAction {
6633da5c369Sopenharmony_ci    sigaction: libc::sigaction
6643da5c369Sopenharmony_ci}
6653da5c369Sopenharmony_ci
6663da5c369Sopenharmony_ciimpl SigAction {
6673da5c369Sopenharmony_ci    /// Creates a new action.
6683da5c369Sopenharmony_ci    ///
6693da5c369Sopenharmony_ci    /// The `SA_SIGINFO` bit in the `flags` argument is ignored (it will be set only if `handler`
6703da5c369Sopenharmony_ci    /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
6713da5c369Sopenharmony_ci    /// the signal-catching function.
6723da5c369Sopenharmony_ci    pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
6733da5c369Sopenharmony_ci        unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
6743da5c369Sopenharmony_ci            (*p).sa_sigaction = match handler {
6753da5c369Sopenharmony_ci                SigHandler::SigDfl => libc::SIG_DFL,
6763da5c369Sopenharmony_ci                SigHandler::SigIgn => libc::SIG_IGN,
6773da5c369Sopenharmony_ci                SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
6783da5c369Sopenharmony_ci                #[cfg(not(target_os = "redox"))]
6793da5c369Sopenharmony_ci                SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
6803da5c369Sopenharmony_ci            };
6813da5c369Sopenharmony_ci        }
6823da5c369Sopenharmony_ci
6833da5c369Sopenharmony_ci        let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
6843da5c369Sopenharmony_ci        unsafe {
6853da5c369Sopenharmony_ci            let p = s.as_mut_ptr();
6863da5c369Sopenharmony_ci            install_sig(p, handler);
6873da5c369Sopenharmony_ci            (*p).sa_flags = match handler {
6883da5c369Sopenharmony_ci                #[cfg(not(target_os = "redox"))]
6893da5c369Sopenharmony_ci                SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
6903da5c369Sopenharmony_ci                _ => (flags - SaFlags::SA_SIGINFO).bits(),
6913da5c369Sopenharmony_ci            };
6923da5c369Sopenharmony_ci            (*p).sa_mask = mask.sigset;
6933da5c369Sopenharmony_ci
6943da5c369Sopenharmony_ci            SigAction { sigaction: s.assume_init() }
6953da5c369Sopenharmony_ci        }
6963da5c369Sopenharmony_ci    }
6973da5c369Sopenharmony_ci
6983da5c369Sopenharmony_ci    /// Returns the flags set on the action.
6993da5c369Sopenharmony_ci    pub fn flags(&self) -> SaFlags {
7003da5c369Sopenharmony_ci        SaFlags::from_bits_truncate(self.sigaction.sa_flags)
7013da5c369Sopenharmony_ci    }
7023da5c369Sopenharmony_ci
7033da5c369Sopenharmony_ci    /// Returns the set of signals that are blocked during execution of the action's
7043da5c369Sopenharmony_ci    /// signal-catching function.
7053da5c369Sopenharmony_ci    pub fn mask(&self) -> SigSet {
7063da5c369Sopenharmony_ci        SigSet { sigset: self.sigaction.sa_mask }
7073da5c369Sopenharmony_ci    }
7083da5c369Sopenharmony_ci
7093da5c369Sopenharmony_ci    /// Returns the action's handler.
7103da5c369Sopenharmony_ci    pub fn handler(&self) -> SigHandler {
7113da5c369Sopenharmony_ci        match self.sigaction.sa_sigaction {
7123da5c369Sopenharmony_ci            libc::SIG_DFL => SigHandler::SigDfl,
7133da5c369Sopenharmony_ci            libc::SIG_IGN => SigHandler::SigIgn,
7143da5c369Sopenharmony_ci            #[cfg(not(target_os = "redox"))]
7153da5c369Sopenharmony_ci            p if self.flags().contains(SaFlags::SA_SIGINFO) =>
7163da5c369Sopenharmony_ci                SigHandler::SigAction(
7173da5c369Sopenharmony_ci                // Safe for one of two reasons:
7183da5c369Sopenharmony_ci                // * The SigHandler was created by SigHandler::new, in which
7193da5c369Sopenharmony_ci                //   case the pointer is correct, or
7203da5c369Sopenharmony_ci                // * The SigHandler was created by signal or sigaction, which
7213da5c369Sopenharmony_ci                //   are unsafe functions, so the caller should've somehow
7223da5c369Sopenharmony_ci                //   ensured that it is correctly initialized.
7233da5c369Sopenharmony_ci                unsafe{
7243da5c369Sopenharmony_ci                    *(&p as *const usize
7253da5c369Sopenharmony_ci                         as *const extern fn(_, _, _))
7263da5c369Sopenharmony_ci                }
7273da5c369Sopenharmony_ci                as extern fn(_, _, _)),
7283da5c369Sopenharmony_ci            p => SigHandler::Handler(
7293da5c369Sopenharmony_ci                // Safe for one of two reasons:
7303da5c369Sopenharmony_ci                // * The SigHandler was created by SigHandler::new, in which
7313da5c369Sopenharmony_ci                //   case the pointer is correct, or
7323da5c369Sopenharmony_ci                // * The SigHandler was created by signal or sigaction, which
7333da5c369Sopenharmony_ci                //   are unsafe functions, so the caller should've somehow
7343da5c369Sopenharmony_ci                //   ensured that it is correctly initialized.
7353da5c369Sopenharmony_ci                unsafe{
7363da5c369Sopenharmony_ci                    *(&p as *const usize
7373da5c369Sopenharmony_ci                         as *const extern fn(libc::c_int))
7383da5c369Sopenharmony_ci                }
7393da5c369Sopenharmony_ci                as extern fn(libc::c_int)),
7403da5c369Sopenharmony_ci        }
7413da5c369Sopenharmony_ci    }
7423da5c369Sopenharmony_ci}
7433da5c369Sopenharmony_ci
7443da5c369Sopenharmony_ci/// Changes the action taken by a process on receipt of a specific signal.
7453da5c369Sopenharmony_ci///
7463da5c369Sopenharmony_ci/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous
7473da5c369Sopenharmony_ci/// action for the given signal. If `sigaction` fails, no new signal handler is installed.
7483da5c369Sopenharmony_ci///
7493da5c369Sopenharmony_ci/// # Safety
7503da5c369Sopenharmony_ci///
7513da5c369Sopenharmony_ci/// * Signal handlers may be called at any point during execution, which limits
7523da5c369Sopenharmony_ci///   what is safe to do in the body of the signal-catching function. Be certain
7533da5c369Sopenharmony_ci///   to only make syscalls that are explicitly marked safe for signal handlers
7543da5c369Sopenharmony_ci///   and only share global data using atomics.
7553da5c369Sopenharmony_ci///
7563da5c369Sopenharmony_ci/// * There is also no guarantee that the old signal handler was installed
7573da5c369Sopenharmony_ci///   correctly.  If it was installed by this crate, it will be.  But if it was
7583da5c369Sopenharmony_ci///   installed by, for example, C code, then there is no guarantee its function
7593da5c369Sopenharmony_ci///   pointer is valid.  In that case, this function effectively dereferences a
7603da5c369Sopenharmony_ci///   raw pointer of unknown provenance.
7613da5c369Sopenharmony_cipub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
7623da5c369Sopenharmony_ci    let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
7633da5c369Sopenharmony_ci
7643da5c369Sopenharmony_ci    let res = libc::sigaction(signal as libc::c_int,
7653da5c369Sopenharmony_ci                              &sigaction.sigaction as *const libc::sigaction,
7663da5c369Sopenharmony_ci                              oldact.as_mut_ptr());
7673da5c369Sopenharmony_ci
7683da5c369Sopenharmony_ci    Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
7693da5c369Sopenharmony_ci}
7703da5c369Sopenharmony_ci
7713da5c369Sopenharmony_ci/// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
7723da5c369Sopenharmony_ci///
7733da5c369Sopenharmony_ci/// Installs `handler` for the given `signal`, returning the previous signal
7743da5c369Sopenharmony_ci/// handler. `signal` should only be used following another call to `signal` or
7753da5c369Sopenharmony_ci/// if the current handler is the default. The return value of `signal` is
7763da5c369Sopenharmony_ci/// undefined after setting the handler with [`sigaction`][SigActionFn].
7773da5c369Sopenharmony_ci///
7783da5c369Sopenharmony_ci/// # Safety
7793da5c369Sopenharmony_ci///
7803da5c369Sopenharmony_ci/// If the pointer to the previous signal handler is invalid, undefined
7813da5c369Sopenharmony_ci/// behavior could be invoked when casting it back to a [`SigAction`][SigActionStruct].
7823da5c369Sopenharmony_ci///
7833da5c369Sopenharmony_ci/// # Examples
7843da5c369Sopenharmony_ci///
7853da5c369Sopenharmony_ci/// Ignore `SIGINT`:
7863da5c369Sopenharmony_ci///
7873da5c369Sopenharmony_ci/// ```no_run
7883da5c369Sopenharmony_ci/// # use nix::sys::signal::{self, Signal, SigHandler};
7893da5c369Sopenharmony_ci/// unsafe { signal::signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
7903da5c369Sopenharmony_ci/// ```
7913da5c369Sopenharmony_ci///
7923da5c369Sopenharmony_ci/// Use a signal handler to set a flag variable:
7933da5c369Sopenharmony_ci///
7943da5c369Sopenharmony_ci/// ```no_run
7953da5c369Sopenharmony_ci/// # #[macro_use] extern crate lazy_static;
7963da5c369Sopenharmony_ci/// # use std::convert::TryFrom;
7973da5c369Sopenharmony_ci/// # use std::sync::atomic::{AtomicBool, Ordering};
7983da5c369Sopenharmony_ci/// # use nix::sys::signal::{self, Signal, SigHandler};
7993da5c369Sopenharmony_ci/// lazy_static! {
8003da5c369Sopenharmony_ci///    static ref SIGNALED: AtomicBool = AtomicBool::new(false);
8013da5c369Sopenharmony_ci/// }
8023da5c369Sopenharmony_ci///
8033da5c369Sopenharmony_ci/// extern fn handle_sigint(signal: libc::c_int) {
8043da5c369Sopenharmony_ci///     let signal = Signal::try_from(signal).unwrap();
8053da5c369Sopenharmony_ci///     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
8063da5c369Sopenharmony_ci/// }
8073da5c369Sopenharmony_ci///
8083da5c369Sopenharmony_ci/// fn main() {
8093da5c369Sopenharmony_ci///     let handler = SigHandler::Handler(handle_sigint);
8103da5c369Sopenharmony_ci///     unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap();
8113da5c369Sopenharmony_ci/// }
8123da5c369Sopenharmony_ci/// ```
8133da5c369Sopenharmony_ci///
8143da5c369Sopenharmony_ci/// # Errors
8153da5c369Sopenharmony_ci///
8163da5c369Sopenharmony_ci/// Returns [`Error(Errno::EOPNOTSUPP)`] if `handler` is
8173da5c369Sopenharmony_ci/// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead.
8183da5c369Sopenharmony_ci///
8193da5c369Sopenharmony_ci/// `signal` also returns any error from `libc::signal`, such as when an attempt
8203da5c369Sopenharmony_ci/// is made to catch a signal that cannot be caught or to ignore a signal that
8213da5c369Sopenharmony_ci/// cannot be ignored.
8223da5c369Sopenharmony_ci///
8233da5c369Sopenharmony_ci/// [`Error::UnsupportedOperation`]: ../../enum.Error.html#variant.UnsupportedOperation
8243da5c369Sopenharmony_ci/// [SigActionStruct]: struct.SigAction.html
8253da5c369Sopenharmony_ci/// [sigactionFn]: fn.sigaction.html
8263da5c369Sopenharmony_cipub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
8273da5c369Sopenharmony_ci    let signal = signal as libc::c_int;
8283da5c369Sopenharmony_ci    let res = match handler {
8293da5c369Sopenharmony_ci        SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
8303da5c369Sopenharmony_ci        SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
8313da5c369Sopenharmony_ci        SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
8323da5c369Sopenharmony_ci        #[cfg(not(target_os = "redox"))]
8333da5c369Sopenharmony_ci        SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
8343da5c369Sopenharmony_ci    };
8353da5c369Sopenharmony_ci    Errno::result(res).map(|oldhandler| {
8363da5c369Sopenharmony_ci        match oldhandler {
8373da5c369Sopenharmony_ci            libc::SIG_DFL => SigHandler::SigDfl,
8383da5c369Sopenharmony_ci            libc::SIG_IGN => SigHandler::SigIgn,
8393da5c369Sopenharmony_ci            p => SigHandler::Handler(
8403da5c369Sopenharmony_ci                *(&p as *const usize
8413da5c369Sopenharmony_ci                     as *const extern fn(libc::c_int))
8423da5c369Sopenharmony_ci                as extern fn(libc::c_int)),
8433da5c369Sopenharmony_ci        }
8443da5c369Sopenharmony_ci    })
8453da5c369Sopenharmony_ci}
8463da5c369Sopenharmony_ci
8473da5c369Sopenharmony_cifn do_pthread_sigmask(how: SigmaskHow,
8483da5c369Sopenharmony_ci                       set: Option<&SigSet>,
8493da5c369Sopenharmony_ci                       oldset: Option<*mut libc::sigset_t>) -> Result<()> {
8503da5c369Sopenharmony_ci    if set.is_none() && oldset.is_none() {
8513da5c369Sopenharmony_ci        return Ok(())
8523da5c369Sopenharmony_ci    }
8533da5c369Sopenharmony_ci
8543da5c369Sopenharmony_ci    let res = unsafe {
8553da5c369Sopenharmony_ci        // if set or oldset is None, pass in null pointers instead
8563da5c369Sopenharmony_ci        libc::pthread_sigmask(how as libc::c_int,
8573da5c369Sopenharmony_ci                             set.map_or_else(ptr::null::<libc::sigset_t>,
8583da5c369Sopenharmony_ci                                             |s| &s.sigset as *const libc::sigset_t),
8593da5c369Sopenharmony_ci                             oldset.unwrap_or(ptr::null_mut())
8603da5c369Sopenharmony_ci                             )
8613da5c369Sopenharmony_ci    };
8623da5c369Sopenharmony_ci
8633da5c369Sopenharmony_ci    Errno::result(res).map(drop)
8643da5c369Sopenharmony_ci}
8653da5c369Sopenharmony_ci
8663da5c369Sopenharmony_ci/// Manages the signal mask (set of blocked signals) for the calling thread.
8673da5c369Sopenharmony_ci///
8683da5c369Sopenharmony_ci/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
8693da5c369Sopenharmony_ci/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
8703da5c369Sopenharmony_ci/// and no modification will take place.
8713da5c369Sopenharmony_ci///
8723da5c369Sopenharmony_ci/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
8733da5c369Sopenharmony_ci///
8743da5c369Sopenharmony_ci/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
8753da5c369Sopenharmony_ci/// and then it will be updated with `set`.
8763da5c369Sopenharmony_ci///
8773da5c369Sopenharmony_ci/// If both `set` and `oldset` is None, this function is a no-op.
8783da5c369Sopenharmony_ci///
8793da5c369Sopenharmony_ci/// For more information, visit the [`pthread_sigmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
8803da5c369Sopenharmony_ci/// or [`sigprocmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
8813da5c369Sopenharmony_cipub fn pthread_sigmask(how: SigmaskHow,
8823da5c369Sopenharmony_ci                       set: Option<&SigSet>,
8833da5c369Sopenharmony_ci                       oldset: Option<&mut SigSet>) -> Result<()>
8843da5c369Sopenharmony_ci{
8853da5c369Sopenharmony_ci    do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
8863da5c369Sopenharmony_ci}
8873da5c369Sopenharmony_ci
8883da5c369Sopenharmony_ci/// Examine and change blocked signals.
8893da5c369Sopenharmony_ci///
8903da5c369Sopenharmony_ci/// For more information see the [`sigprocmask` man
8913da5c369Sopenharmony_ci/// pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
8923da5c369Sopenharmony_cipub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
8933da5c369Sopenharmony_ci    if set.is_none() && oldset.is_none() {
8943da5c369Sopenharmony_ci        return Ok(())
8953da5c369Sopenharmony_ci    }
8963da5c369Sopenharmony_ci
8973da5c369Sopenharmony_ci    let res = unsafe {
8983da5c369Sopenharmony_ci        // if set or oldset is None, pass in null pointers instead
8993da5c369Sopenharmony_ci        libc::sigprocmask(how as libc::c_int,
9003da5c369Sopenharmony_ci                          set.map_or_else(ptr::null::<libc::sigset_t>,
9013da5c369Sopenharmony_ci                                          |s| &s.sigset as *const libc::sigset_t),
9023da5c369Sopenharmony_ci                          oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
9033da5c369Sopenharmony_ci                                             |os| &mut os.sigset as *mut libc::sigset_t))
9043da5c369Sopenharmony_ci    };
9053da5c369Sopenharmony_ci
9063da5c369Sopenharmony_ci    Errno::result(res).map(drop)
9073da5c369Sopenharmony_ci}
9083da5c369Sopenharmony_ci
9093da5c369Sopenharmony_ci/// Send a signal to a process
9103da5c369Sopenharmony_ci///
9113da5c369Sopenharmony_ci/// # Arguments
9123da5c369Sopenharmony_ci///
9133da5c369Sopenharmony_ci/// * `pid` -    Specifies which processes should receive the signal.
9143da5c369Sopenharmony_ci///   - If positive, specifies an individual process.
9153da5c369Sopenharmony_ci///   - If zero, the signal will be sent to all processes whose group
9163da5c369Sopenharmony_ci///     ID is equal to the process group ID of the sender.  This is a
9173da5c369Sopenharmony_ci#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
9183da5c369Sopenharmony_ci#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
9193da5c369Sopenharmony_ci///   - If `-1` and the process has super-user privileges, the signal
9203da5c369Sopenharmony_ci///     is sent to all processes exclusing system processes.
9213da5c369Sopenharmony_ci///   - If less than `-1`, the signal is sent to all processes whose
9223da5c369Sopenharmony_ci///     process group ID is equal to the absolute value of `pid`.
9233da5c369Sopenharmony_ci/// * `signal` - Signal to send. If `None`, error checking is performed
9243da5c369Sopenharmony_ci///              but no signal is actually sent.
9253da5c369Sopenharmony_ci///
9263da5c369Sopenharmony_ci/// See Also
9273da5c369Sopenharmony_ci/// [`kill(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html)
9283da5c369Sopenharmony_cipub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
9293da5c369Sopenharmony_ci    let res = unsafe { libc::kill(pid.into(),
9303da5c369Sopenharmony_ci                                  match signal.into() {
9313da5c369Sopenharmony_ci                                      Some(s) => s as libc::c_int,
9323da5c369Sopenharmony_ci                                      None => 0,
9333da5c369Sopenharmony_ci                                  }) };
9343da5c369Sopenharmony_ci
9353da5c369Sopenharmony_ci    Errno::result(res).map(drop)
9363da5c369Sopenharmony_ci}
9373da5c369Sopenharmony_ci
9383da5c369Sopenharmony_ci/// Send a signal to a process group
9393da5c369Sopenharmony_ci///
9403da5c369Sopenharmony_ci/// # Arguments
9413da5c369Sopenharmony_ci///
9423da5c369Sopenharmony_ci/// * `pgrp` -   Process group to signal.  If less then or equal 1, the behavior
9433da5c369Sopenharmony_ci///              is platform-specific.
9443da5c369Sopenharmony_ci/// * `signal` - Signal to send. If `None`, `killpg` will only preform error
9453da5c369Sopenharmony_ci///              checking and won't send any signal.
9463da5c369Sopenharmony_ci///
9473da5c369Sopenharmony_ci/// See Also [killpg(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
9483da5c369Sopenharmony_ci#[cfg(not(target_os = "fuchsia"))]
9493da5c369Sopenharmony_cipub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
9503da5c369Sopenharmony_ci    let res = unsafe { libc::killpg(pgrp.into(),
9513da5c369Sopenharmony_ci                                  match signal.into() {
9523da5c369Sopenharmony_ci                                      Some(s) => s as libc::c_int,
9533da5c369Sopenharmony_ci                                      None => 0,
9543da5c369Sopenharmony_ci                                  }) };
9553da5c369Sopenharmony_ci
9563da5c369Sopenharmony_ci    Errno::result(res).map(drop)
9573da5c369Sopenharmony_ci}
9583da5c369Sopenharmony_ci
9593da5c369Sopenharmony_ci/// Send a signal to the current thread
9603da5c369Sopenharmony_ci///
9613da5c369Sopenharmony_ci/// See Also [raise(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html)
9623da5c369Sopenharmony_cipub fn raise(signal: Signal) -> Result<()> {
9633da5c369Sopenharmony_ci    let res = unsafe { libc::raise(signal as libc::c_int) };
9643da5c369Sopenharmony_ci
9653da5c369Sopenharmony_ci    Errno::result(res).map(drop)
9663da5c369Sopenharmony_ci}
9673da5c369Sopenharmony_ci}
9683da5c369Sopenharmony_ci
9693da5c369Sopenharmony_cifeature! {
9703da5c369Sopenharmony_ci#![any(feature = "aio", feature = "signal")]
9713da5c369Sopenharmony_ci
9723da5c369Sopenharmony_ci/// Identifies a thread for [`SigevNotify::SigevThreadId`]
9733da5c369Sopenharmony_ci#[cfg(target_os = "freebsd")]
9743da5c369Sopenharmony_cipub type type_of_thread_id = libc::lwpid_t;
9753da5c369Sopenharmony_ci/// Identifies a thread for [`SigevNotify::SigevThreadId`]
9763da5c369Sopenharmony_ci#[cfg(target_os = "linux")]
9773da5c369Sopenharmony_cipub type type_of_thread_id = libc::pid_t;
9783da5c369Sopenharmony_ci
9793da5c369Sopenharmony_ci/// Specifies the notification method used by a [`SigEvent`]
9803da5c369Sopenharmony_ci// sigval is actually a union of a int and a void*.  But it's never really used
9813da5c369Sopenharmony_ci// as a pointer, because neither libc nor the kernel ever dereference it.  nix
9823da5c369Sopenharmony_ci// therefore presents it as an intptr_t, which is how kevent uses it.
9833da5c369Sopenharmony_ci#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
9843da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
9853da5c369Sopenharmony_cipub enum SigevNotify {
9863da5c369Sopenharmony_ci    /// No notification will be delivered
9873da5c369Sopenharmony_ci    SigevNone,
9883da5c369Sopenharmony_ci    /// Notify by delivering a signal to the process.
9893da5c369Sopenharmony_ci    SigevSignal {
9903da5c369Sopenharmony_ci        /// Signal to deliver
9913da5c369Sopenharmony_ci        signal: Signal,
9923da5c369Sopenharmony_ci        /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
9933da5c369Sopenharmony_ci        /// structure of the queued signal.
9943da5c369Sopenharmony_ci        si_value: libc::intptr_t
9953da5c369Sopenharmony_ci    },
9963da5c369Sopenharmony_ci    // Note: SIGEV_THREAD is not implemented because libc::sigevent does not
9973da5c369Sopenharmony_ci    // expose a way to set the union members needed by SIGEV_THREAD.
9983da5c369Sopenharmony_ci    /// Notify by delivering an event to a kqueue.
9993da5c369Sopenharmony_ci    #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
10003da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
10013da5c369Sopenharmony_ci    SigevKevent {
10023da5c369Sopenharmony_ci        /// File descriptor of the kqueue to notify.
10033da5c369Sopenharmony_ci        kq: RawFd,
10043da5c369Sopenharmony_ci        /// Will be contained in the kevent's `udata` field.
10053da5c369Sopenharmony_ci        udata: libc::intptr_t
10063da5c369Sopenharmony_ci    },
10073da5c369Sopenharmony_ci    /// Notify by delivering a signal to a thread.
10083da5c369Sopenharmony_ci    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
10093da5c369Sopenharmony_ci    #[cfg_attr(docsrs, doc(cfg(all())))]
10103da5c369Sopenharmony_ci    SigevThreadId {
10113da5c369Sopenharmony_ci        /// Signal to send
10123da5c369Sopenharmony_ci        signal: Signal,
10133da5c369Sopenharmony_ci        /// LWP ID of the thread to notify
10143da5c369Sopenharmony_ci        thread_id: type_of_thread_id,
10153da5c369Sopenharmony_ci        /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
10163da5c369Sopenharmony_ci        /// structure of the queued signal.
10173da5c369Sopenharmony_ci        si_value: libc::intptr_t
10183da5c369Sopenharmony_ci    },
10193da5c369Sopenharmony_ci}
10203da5c369Sopenharmony_ci}
10213da5c369Sopenharmony_ci
10223da5c369Sopenharmony_ci#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
10233da5c369Sopenharmony_ci#[cfg_attr(docsrs, doc(cfg(all())))]
10243da5c369Sopenharmony_cimod sigevent {
10253da5c369Sopenharmony_ci    feature! {
10263da5c369Sopenharmony_ci    #![any(feature = "aio", feature = "signal")]
10273da5c369Sopenharmony_ci
10283da5c369Sopenharmony_ci    use std::mem;
10293da5c369Sopenharmony_ci    use std::ptr;
10303da5c369Sopenharmony_ci    use super::SigevNotify;
10313da5c369Sopenharmony_ci    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
10323da5c369Sopenharmony_ci    use super::type_of_thread_id;
10333da5c369Sopenharmony_ci
10343da5c369Sopenharmony_ci    /// Used to request asynchronous notification of the completion of certain
10353da5c369Sopenharmony_ci    /// events, such as POSIX AIO and timers.
10363da5c369Sopenharmony_ci    #[repr(C)]
10373da5c369Sopenharmony_ci    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
10383da5c369Sopenharmony_ci    pub struct SigEvent {
10393da5c369Sopenharmony_ci        sigevent: libc::sigevent
10403da5c369Sopenharmony_ci    }
10413da5c369Sopenharmony_ci
10423da5c369Sopenharmony_ci    impl SigEvent {
10433da5c369Sopenharmony_ci        /// **Note:** this constructor does not allow the user to set the
10443da5c369Sopenharmony_ci        /// `sigev_notify_kevent_flags` field.  That's considered ok because on FreeBSD
10453da5c369Sopenharmony_ci        /// at least those flags don't do anything useful.  That field is part of a
10463da5c369Sopenharmony_ci        /// union that shares space with the more genuinely useful fields.
10473da5c369Sopenharmony_ci        ///
10483da5c369Sopenharmony_ci        /// **Note:** This constructor also doesn't allow the caller to set the
10493da5c369Sopenharmony_ci        /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
10503da5c369Sopenharmony_ci        /// required for `SIGEV_THREAD`.  That's considered ok because on no operating
10513da5c369Sopenharmony_ci        /// system is `SIGEV_THREAD` the most efficient way to deliver AIO
10523da5c369Sopenharmony_ci        /// notification.  FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
10533da5c369Sopenharmony_ci        /// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
10543da5c369Sopenharmony_ci        /// `SIGEV_SIGNAL`.  That field is part of a union that shares space with the
10553da5c369Sopenharmony_ci        /// more genuinely useful `sigev_notify_thread_id`
10563da5c369Sopenharmony_ci        // Allow invalid_value warning on Fuchsia only.
10573da5c369Sopenharmony_ci        // See https://github.com/nix-rust/nix/issues/1441
10583da5c369Sopenharmony_ci        #[cfg_attr(target_os = "fuchsia", allow(invalid_value))]
10593da5c369Sopenharmony_ci        pub fn new(sigev_notify: SigevNotify) -> SigEvent {
10603da5c369Sopenharmony_ci            let mut sev = unsafe { mem::MaybeUninit::<libc::sigevent>::zeroed().assume_init() };
10613da5c369Sopenharmony_ci            sev.sigev_notify = match sigev_notify {
10623da5c369Sopenharmony_ci                SigevNotify::SigevNone => libc::SIGEV_NONE,
10633da5c369Sopenharmony_ci                SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
10643da5c369Sopenharmony_ci                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
10653da5c369Sopenharmony_ci                SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
10663da5c369Sopenharmony_ci                #[cfg(target_os = "freebsd")]
10673da5c369Sopenharmony_ci                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
10683da5c369Sopenharmony_ci                #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
10693da5c369Sopenharmony_ci                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
10703da5c369Sopenharmony_ci                #[cfg(all(target_os = "linux", target_env = "uclibc"))]
10713da5c369Sopenharmony_ci                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
10723da5c369Sopenharmony_ci                #[cfg(any(all(target_os = "linux", any(target_env = "musl", target_env = "ohos")), target_arch = "mips"))]
10733da5c369Sopenharmony_ci                SigevNotify::SigevThreadId{..} => 4  // No SIGEV_THREAD_ID defined
10743da5c369Sopenharmony_ci            };
10753da5c369Sopenharmony_ci            sev.sigev_signo = match sigev_notify {
10763da5c369Sopenharmony_ci                SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
10773da5c369Sopenharmony_ci                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
10783da5c369Sopenharmony_ci                SigevNotify::SigevKevent{ kq, ..} => kq,
10793da5c369Sopenharmony_ci                #[cfg(any(target_os = "linux", target_os = "freebsd"))]
10803da5c369Sopenharmony_ci                SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
10813da5c369Sopenharmony_ci                _ => 0
10823da5c369Sopenharmony_ci            };
10833da5c369Sopenharmony_ci            sev.sigev_value.sival_ptr = match sigev_notify {
10843da5c369Sopenharmony_ci                SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
10853da5c369Sopenharmony_ci                SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
10863da5c369Sopenharmony_ci                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
10873da5c369Sopenharmony_ci                SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
10883da5c369Sopenharmony_ci                #[cfg(any(target_os = "freebsd", target_os = "linux"))]
10893da5c369Sopenharmony_ci                SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
10903da5c369Sopenharmony_ci            };
10913da5c369Sopenharmony_ci            SigEvent::set_tid(&mut sev, &sigev_notify);
10923da5c369Sopenharmony_ci            SigEvent{sigevent: sev}
10933da5c369Sopenharmony_ci        }
10943da5c369Sopenharmony_ci
10953da5c369Sopenharmony_ci        #[cfg(any(target_os = "freebsd", target_os = "linux"))]
10963da5c369Sopenharmony_ci        fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
10973da5c369Sopenharmony_ci            sev.sigev_notify_thread_id = match *sigev_notify {
10983da5c369Sopenharmony_ci                SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
10993da5c369Sopenharmony_ci                _ => 0 as type_of_thread_id
11003da5c369Sopenharmony_ci            };
11013da5c369Sopenharmony_ci        }
11023da5c369Sopenharmony_ci
11033da5c369Sopenharmony_ci        #[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
11043da5c369Sopenharmony_ci        fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
11053da5c369Sopenharmony_ci        }
11063da5c369Sopenharmony_ci
11073da5c369Sopenharmony_ci        /// Return a copy of the inner structure
11083da5c369Sopenharmony_ci        pub fn sigevent(&self) -> libc::sigevent {
11093da5c369Sopenharmony_ci            self.sigevent
11103da5c369Sopenharmony_ci        }
11113da5c369Sopenharmony_ci
11123da5c369Sopenharmony_ci        /// Returns a mutable pointer to the `sigevent` wrapped by `self`
11133da5c369Sopenharmony_ci        pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
11143da5c369Sopenharmony_ci            &mut self.sigevent
11153da5c369Sopenharmony_ci        }
11163da5c369Sopenharmony_ci    }
11173da5c369Sopenharmony_ci
11183da5c369Sopenharmony_ci    impl<'a> From<&'a libc::sigevent> for SigEvent {
11193da5c369Sopenharmony_ci        fn from(sigevent: &libc::sigevent) -> Self {
11203da5c369Sopenharmony_ci            SigEvent{ sigevent: *sigevent }
11213da5c369Sopenharmony_ci        }
11223da5c369Sopenharmony_ci    }
11233da5c369Sopenharmony_ci    }
11243da5c369Sopenharmony_ci}
11253da5c369Sopenharmony_ci
11263da5c369Sopenharmony_ci#[cfg(test)]
11273da5c369Sopenharmony_cimod tests {
11283da5c369Sopenharmony_ci    use super::*;
11293da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
11303da5c369Sopenharmony_ci    use std::thread;
11313da5c369Sopenharmony_ci
11323da5c369Sopenharmony_ci    #[test]
11333da5c369Sopenharmony_ci    fn test_contains() {
11343da5c369Sopenharmony_ci        let mut mask = SigSet::empty();
11353da5c369Sopenharmony_ci        mask.add(SIGUSR1);
11363da5c369Sopenharmony_ci
11373da5c369Sopenharmony_ci        assert!(mask.contains(SIGUSR1));
11383da5c369Sopenharmony_ci        assert!(!mask.contains(SIGUSR2));
11393da5c369Sopenharmony_ci
11403da5c369Sopenharmony_ci        let all = SigSet::all();
11413da5c369Sopenharmony_ci        assert!(all.contains(SIGUSR1));
11423da5c369Sopenharmony_ci        assert!(all.contains(SIGUSR2));
11433da5c369Sopenharmony_ci    }
11443da5c369Sopenharmony_ci
11453da5c369Sopenharmony_ci    #[test]
11463da5c369Sopenharmony_ci    fn test_clear() {
11473da5c369Sopenharmony_ci        let mut set = SigSet::all();
11483da5c369Sopenharmony_ci        set.clear();
11493da5c369Sopenharmony_ci        for signal in Signal::iterator() {
11503da5c369Sopenharmony_ci            assert!(!set.contains(signal));
11513da5c369Sopenharmony_ci        }
11523da5c369Sopenharmony_ci    }
11533da5c369Sopenharmony_ci
11543da5c369Sopenharmony_ci    #[test]
11553da5c369Sopenharmony_ci    fn test_from_str_round_trips() {
11563da5c369Sopenharmony_ci        for signal in Signal::iterator() {
11573da5c369Sopenharmony_ci            assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
11583da5c369Sopenharmony_ci            assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
11593da5c369Sopenharmony_ci        }
11603da5c369Sopenharmony_ci    }
11613da5c369Sopenharmony_ci
11623da5c369Sopenharmony_ci    #[test]
11633da5c369Sopenharmony_ci    fn test_from_str_invalid_value() {
11643da5c369Sopenharmony_ci        let errval = Err(Errno::EINVAL);
11653da5c369Sopenharmony_ci        assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
11663da5c369Sopenharmony_ci        assert_eq!("kill".parse::<Signal>(), errval);
11673da5c369Sopenharmony_ci        assert_eq!("9".parse::<Signal>(), errval);
11683da5c369Sopenharmony_ci    }
11693da5c369Sopenharmony_ci
11703da5c369Sopenharmony_ci    #[test]
11713da5c369Sopenharmony_ci    fn test_extend() {
11723da5c369Sopenharmony_ci        let mut one_signal = SigSet::empty();
11733da5c369Sopenharmony_ci        one_signal.add(SIGUSR1);
11743da5c369Sopenharmony_ci
11753da5c369Sopenharmony_ci        let mut two_signals = SigSet::empty();
11763da5c369Sopenharmony_ci        two_signals.add(SIGUSR2);
11773da5c369Sopenharmony_ci        two_signals.extend(&one_signal);
11783da5c369Sopenharmony_ci
11793da5c369Sopenharmony_ci        assert!(two_signals.contains(SIGUSR1));
11803da5c369Sopenharmony_ci        assert!(two_signals.contains(SIGUSR2));
11813da5c369Sopenharmony_ci    }
11823da5c369Sopenharmony_ci
11833da5c369Sopenharmony_ci    #[test]
11843da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
11853da5c369Sopenharmony_ci    fn test_thread_signal_set_mask() {
11863da5c369Sopenharmony_ci        thread::spawn(|| {
11873da5c369Sopenharmony_ci            let prev_mask = SigSet::thread_get_mask()
11883da5c369Sopenharmony_ci                .expect("Failed to get existing signal mask!");
11893da5c369Sopenharmony_ci
11903da5c369Sopenharmony_ci            let mut test_mask = prev_mask;
11913da5c369Sopenharmony_ci            test_mask.add(SIGUSR1);
11923da5c369Sopenharmony_ci
11933da5c369Sopenharmony_ci            test_mask.thread_set_mask().expect("assertion failed");
11943da5c369Sopenharmony_ci            let new_mask =
11953da5c369Sopenharmony_ci                SigSet::thread_get_mask().expect("Failed to get new mask!");
11963da5c369Sopenharmony_ci
11973da5c369Sopenharmony_ci            assert!(new_mask.contains(SIGUSR1));
11983da5c369Sopenharmony_ci            assert!(!new_mask.contains(SIGUSR2));
11993da5c369Sopenharmony_ci
12003da5c369Sopenharmony_ci            prev_mask
12013da5c369Sopenharmony_ci                .thread_set_mask()
12023da5c369Sopenharmony_ci                .expect("Failed to revert signal mask!");
12033da5c369Sopenharmony_ci        })
12043da5c369Sopenharmony_ci        .join()
12053da5c369Sopenharmony_ci        .unwrap();
12063da5c369Sopenharmony_ci    }
12073da5c369Sopenharmony_ci
12083da5c369Sopenharmony_ci    #[test]
12093da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
12103da5c369Sopenharmony_ci    fn test_thread_signal_block() {
12113da5c369Sopenharmony_ci        thread::spawn(|| {
12123da5c369Sopenharmony_ci            let mut mask = SigSet::empty();
12133da5c369Sopenharmony_ci            mask.add(SIGUSR1);
12143da5c369Sopenharmony_ci
12153da5c369Sopenharmony_ci            mask.thread_block().expect("assertion failed");
12163da5c369Sopenharmony_ci
12173da5c369Sopenharmony_ci            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
12183da5c369Sopenharmony_ci        })
12193da5c369Sopenharmony_ci        .join()
12203da5c369Sopenharmony_ci        .unwrap();
12213da5c369Sopenharmony_ci    }
12223da5c369Sopenharmony_ci
12233da5c369Sopenharmony_ci    #[test]
12243da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
12253da5c369Sopenharmony_ci    fn test_thread_signal_unblock() {
12263da5c369Sopenharmony_ci        thread::spawn(|| {
12273da5c369Sopenharmony_ci            let mut mask = SigSet::empty();
12283da5c369Sopenharmony_ci            mask.add(SIGUSR1);
12293da5c369Sopenharmony_ci
12303da5c369Sopenharmony_ci            mask.thread_unblock().expect("assertion failed");
12313da5c369Sopenharmony_ci
12323da5c369Sopenharmony_ci            assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
12333da5c369Sopenharmony_ci        })
12343da5c369Sopenharmony_ci        .join()
12353da5c369Sopenharmony_ci        .unwrap();
12363da5c369Sopenharmony_ci    }
12373da5c369Sopenharmony_ci
12383da5c369Sopenharmony_ci    #[test]
12393da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
12403da5c369Sopenharmony_ci    fn test_thread_signal_swap() {
12413da5c369Sopenharmony_ci        thread::spawn(|| {
12423da5c369Sopenharmony_ci            let mut mask = SigSet::empty();
12433da5c369Sopenharmony_ci            mask.add(SIGUSR1);
12443da5c369Sopenharmony_ci            mask.thread_block().unwrap();
12453da5c369Sopenharmony_ci
12463da5c369Sopenharmony_ci            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
12473da5c369Sopenharmony_ci
12483da5c369Sopenharmony_ci            let mut mask2 = SigSet::empty();
12493da5c369Sopenharmony_ci            mask2.add(SIGUSR2);
12503da5c369Sopenharmony_ci
12513da5c369Sopenharmony_ci            let oldmask =
12523da5c369Sopenharmony_ci                mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap();
12533da5c369Sopenharmony_ci
12543da5c369Sopenharmony_ci            assert!(oldmask.contains(SIGUSR1));
12553da5c369Sopenharmony_ci            assert!(!oldmask.contains(SIGUSR2));
12563da5c369Sopenharmony_ci
12573da5c369Sopenharmony_ci            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
12583da5c369Sopenharmony_ci        })
12593da5c369Sopenharmony_ci        .join()
12603da5c369Sopenharmony_ci        .unwrap();
12613da5c369Sopenharmony_ci    }
12623da5c369Sopenharmony_ci
12633da5c369Sopenharmony_ci    #[test]
12643da5c369Sopenharmony_ci    fn test_from_and_into_iterator() {
12653da5c369Sopenharmony_ci        let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
12663da5c369Sopenharmony_ci        let signals = sigset.into_iter().collect::<Vec<Signal>>();
12673da5c369Sopenharmony_ci        assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
12683da5c369Sopenharmony_ci    }
12693da5c369Sopenharmony_ci
12703da5c369Sopenharmony_ci    #[test]
12713da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
12723da5c369Sopenharmony_ci    fn test_sigaction() {
12733da5c369Sopenharmony_ci        thread::spawn(|| {
12743da5c369Sopenharmony_ci            extern "C" fn test_sigaction_handler(_: libc::c_int) {}
12753da5c369Sopenharmony_ci            extern "C" fn test_sigaction_action(
12763da5c369Sopenharmony_ci                _: libc::c_int,
12773da5c369Sopenharmony_ci                _: *mut libc::siginfo_t,
12783da5c369Sopenharmony_ci                _: *mut libc::c_void,
12793da5c369Sopenharmony_ci            ) {
12803da5c369Sopenharmony_ci            }
12813da5c369Sopenharmony_ci
12823da5c369Sopenharmony_ci            let handler_sig = SigHandler::Handler(test_sigaction_handler);
12833da5c369Sopenharmony_ci
12843da5c369Sopenharmony_ci            let flags =
12853da5c369Sopenharmony_ci                SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO;
12863da5c369Sopenharmony_ci
12873da5c369Sopenharmony_ci            let mut mask = SigSet::empty();
12883da5c369Sopenharmony_ci            mask.add(SIGUSR1);
12893da5c369Sopenharmony_ci
12903da5c369Sopenharmony_ci            let action_sig = SigAction::new(handler_sig, flags, mask);
12913da5c369Sopenharmony_ci
12923da5c369Sopenharmony_ci            assert_eq!(
12933da5c369Sopenharmony_ci                action_sig.flags(),
12943da5c369Sopenharmony_ci                SaFlags::SA_ONSTACK | SaFlags::SA_RESTART
12953da5c369Sopenharmony_ci            );
12963da5c369Sopenharmony_ci            assert_eq!(action_sig.handler(), handler_sig);
12973da5c369Sopenharmony_ci
12983da5c369Sopenharmony_ci            mask = action_sig.mask();
12993da5c369Sopenharmony_ci            assert!(mask.contains(SIGUSR1));
13003da5c369Sopenharmony_ci            assert!(!mask.contains(SIGUSR2));
13013da5c369Sopenharmony_ci
13023da5c369Sopenharmony_ci            let handler_act = SigHandler::SigAction(test_sigaction_action);
13033da5c369Sopenharmony_ci            let action_act = SigAction::new(handler_act, flags, mask);
13043da5c369Sopenharmony_ci            assert_eq!(action_act.handler(), handler_act);
13053da5c369Sopenharmony_ci
13063da5c369Sopenharmony_ci            let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
13073da5c369Sopenharmony_ci            assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
13083da5c369Sopenharmony_ci
13093da5c369Sopenharmony_ci            let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
13103da5c369Sopenharmony_ci            assert_eq!(action_ign.handler(), SigHandler::SigIgn);
13113da5c369Sopenharmony_ci        })
13123da5c369Sopenharmony_ci        .join()
13133da5c369Sopenharmony_ci        .unwrap();
13143da5c369Sopenharmony_ci    }
13153da5c369Sopenharmony_ci
13163da5c369Sopenharmony_ci    #[test]
13173da5c369Sopenharmony_ci    #[cfg(not(target_os = "redox"))]
13183da5c369Sopenharmony_ci    fn test_sigwait() {
13193da5c369Sopenharmony_ci        thread::spawn(|| {
13203da5c369Sopenharmony_ci            let mut mask = SigSet::empty();
13213da5c369Sopenharmony_ci            mask.add(SIGUSR1);
13223da5c369Sopenharmony_ci            mask.add(SIGUSR2);
13233da5c369Sopenharmony_ci            mask.thread_block().unwrap();
13243da5c369Sopenharmony_ci
13253da5c369Sopenharmony_ci            raise(SIGUSR1).unwrap();
13263da5c369Sopenharmony_ci            assert_eq!(mask.wait().unwrap(), SIGUSR1);
13273da5c369Sopenharmony_ci        })
13283da5c369Sopenharmony_ci        .join()
13293da5c369Sopenharmony_ci        .unwrap();
13303da5c369Sopenharmony_ci    }
13313da5c369Sopenharmony_ci
13323da5c369Sopenharmony_ci    #[test]
13333da5c369Sopenharmony_ci    fn test_from_sigset_t_unchecked() {
13343da5c369Sopenharmony_ci        let src_set = SigSet::empty();
13353da5c369Sopenharmony_ci        let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
13363da5c369Sopenharmony_ci
13373da5c369Sopenharmony_ci        for signal in Signal::iterator() {
13383da5c369Sopenharmony_ci            assert!(!set.contains(signal));
13393da5c369Sopenharmony_ci        }
13403da5c369Sopenharmony_ci
13413da5c369Sopenharmony_ci        let src_set = SigSet::all();
13423da5c369Sopenharmony_ci        let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
13433da5c369Sopenharmony_ci
13443da5c369Sopenharmony_ci        for signal in Signal::iterator() {
13453da5c369Sopenharmony_ci            assert!(set.contains(signal));
13463da5c369Sopenharmony_ci        }
13473da5c369Sopenharmony_ci    }
13483da5c369Sopenharmony_ci}
1349