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<OSTOP) 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