use libc;
use {Error, Result};
use errno::Errno;
use std::mem;
use std::fmt;
use std::str::FromStr;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
use std::os::unix::io::RawFd;
use std::ptr;
#[cfg(not(target_os = "openbsd"))]
pub use self::sigevent::*;
libc_enum!{
    
    
    
    
    #[repr(i32)]
    pub enum Signal {
        SIGHUP,
        SIGINT,
        SIGQUIT,
        SIGILL,
        SIGTRAP,
        SIGABRT,
        SIGBUS,
        SIGFPE,
        SIGKILL,
        SIGUSR1,
        SIGSEGV,
        SIGUSR2,
        SIGPIPE,
        SIGALRM,
        SIGTERM,
        #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
                  not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
        SIGSTKFLT,
        SIGCHLD,
        SIGCONT,
        SIGSTOP,
        SIGTSTP,
        SIGTTIN,
        SIGTTOU,
        SIGURG,
        SIGXCPU,
        SIGXFSZ,
        SIGVTALRM,
        SIGPROF,
        SIGWINCH,
        SIGIO,
        #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
        SIGPWR,
        SIGSYS,
        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
        SIGEMT,
        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
        SIGINFO,
    }
}
impl FromStr for Signal {
    type Err = Error;
    fn from_str(s: &str) -> Result<Signal> {
        Ok(match s {
            "SIGHUP" => Signal::SIGHUP,
            "SIGINT" => Signal::SIGINT,
            "SIGQUIT" => Signal::SIGQUIT,
            "SIGILL" => Signal::SIGILL,
            "SIGTRAP" => Signal::SIGTRAP,
            "SIGABRT" => Signal::SIGABRT,
            "SIGBUS" => Signal::SIGBUS,
            "SIGFPE" => Signal::SIGFPE,
            "SIGKILL" => Signal::SIGKILL,
            "SIGUSR1" => Signal::SIGUSR1,
            "SIGSEGV" => Signal::SIGSEGV,
            "SIGUSR2" => Signal::SIGUSR2,
            "SIGPIPE" => Signal::SIGPIPE,
            "SIGALRM" => Signal::SIGALRM,
            "SIGTERM" => Signal::SIGTERM,
            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
            "SIGSTKFLT" => Signal::SIGSTKFLT,
            "SIGCHLD" => Signal::SIGCHLD,
            "SIGCONT" => Signal::SIGCONT,
            "SIGSTOP" => Signal::SIGSTOP,
            "SIGTSTP" => Signal::SIGTSTP,
            "SIGTTIN" => Signal::SIGTTIN,
            "SIGTTOU" => Signal::SIGTTOU,
            "SIGURG" => Signal::SIGURG,
            "SIGXCPU" => Signal::SIGXCPU,
            "SIGXFSZ" => Signal::SIGXFSZ,
            "SIGVTALRM" => Signal::SIGVTALRM,
            "SIGPROF" => Signal::SIGPROF,
            "SIGWINCH" => Signal::SIGWINCH,
            "SIGIO" => Signal::SIGIO,
            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
            "SIGPWR" => Signal::SIGPWR,
            "SIGSYS" => Signal::SIGSYS,
            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
            "SIGEMT" => Signal::SIGEMT,
            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
            "SIGINFO" => Signal::SIGINFO,
            _ => return Err(Error::invalid_argument()),
        })
    }
}
impl AsRef<str> for Signal {
    fn as_ref(&self) -> &str {
        match *self {
            Signal::SIGHUP => "SIGHUP",
            Signal::SIGINT => "SIGINT",
            Signal::SIGQUIT => "SIGQUIT",
            Signal::SIGILL => "SIGILL",
            Signal::SIGTRAP => "SIGTRAP",
            Signal::SIGABRT => "SIGABRT",
            Signal::SIGBUS => "SIGBUS",
            Signal::SIGFPE => "SIGFPE",
            Signal::SIGKILL => "SIGKILL",
            Signal::SIGUSR1 => "SIGUSR1",
            Signal::SIGSEGV => "SIGSEGV",
            Signal::SIGUSR2 => "SIGUSR2",
            Signal::SIGPIPE => "SIGPIPE",
            Signal::SIGALRM => "SIGALRM",
            Signal::SIGTERM => "SIGTERM",
            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
            Signal::SIGSTKFLT => "SIGSTKFLT",
            Signal::SIGCHLD => "SIGCHLD",
            Signal::SIGCONT => "SIGCONT",
            Signal::SIGSTOP => "SIGSTOP",
            Signal::SIGTSTP => "SIGTSTP",
            Signal::SIGTTIN => "SIGTTIN",
            Signal::SIGTTOU => "SIGTTOU",
            Signal::SIGURG => "SIGURG",
            Signal::SIGXCPU => "SIGXCPU",
            Signal::SIGXFSZ => "SIGXFSZ",
            Signal::SIGVTALRM => "SIGVTALRM",
            Signal::SIGPROF => "SIGPROF",
            Signal::SIGWINCH => "SIGWINCH",
            Signal::SIGIO => "SIGIO",
            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
            Signal::SIGPWR => "SIGPWR",
            Signal::SIGSYS => "SIGSYS",
            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
            Signal::SIGEMT => "SIGEMT",
            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
            Signal::SIGINFO => "SIGINFO",
        }
    }
}
impl fmt::Display for Signal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.as_ref())
    }
}
pub use self::Signal::*;
#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
const SIGNALS: [Signal; 31] = [
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGTRAP,
    SIGABRT,
    SIGBUS,
    SIGFPE,
    SIGKILL,
    SIGUSR1,
    SIGSEGV,
    SIGUSR2,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGSTKFLT,
    SIGCHLD,
    SIGCONT,
    SIGSTOP,
    SIGTSTP,
    SIGTTIN,
    SIGTTOU,
    SIGURG,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGIO,
    SIGPWR,
    SIGSYS];
#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")))]
const SIGNALS: [Signal; 30] = [
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGTRAP,
    SIGABRT,
    SIGBUS,
    SIGFPE,
    SIGKILL,
    SIGUSR1,
    SIGSEGV,
    SIGUSR2,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGCHLD,
    SIGCONT,
    SIGSTOP,
    SIGTSTP,
    SIGTTIN,
    SIGTTOU,
    SIGURG,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGIO,
    SIGPWR,
    SIGSYS];
#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
const SIGNALS: [Signal; 31] = [
    SIGHUP,
    SIGINT,
    SIGQUIT,
    SIGILL,
    SIGTRAP,
    SIGABRT,
    SIGBUS,
    SIGFPE,
    SIGKILL,
    SIGUSR1,
    SIGSEGV,
    SIGUSR2,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGCHLD,
    SIGCONT,
    SIGSTOP,
    SIGTSTP,
    SIGTTIN,
    SIGTTOU,
    SIGURG,
    SIGXCPU,
    SIGXFSZ,
    SIGVTALRM,
    SIGPROF,
    SIGWINCH,
    SIGIO,
    SIGSYS,
    SIGEMT,
    SIGINFO];
pub const NSIG: libc::c_int = 32;
#[derive(Clone, Copy)]
#[allow(missing_debug_implementations)]
pub struct SignalIterator {
    next: usize,
}
impl Iterator for SignalIterator {
    type Item = Signal;
    fn next(&mut self) -> Option<Signal> {
        if self.next < SIGNALS.len() {
            let next_signal = SIGNALS[self.next];
            self.next += 1;
            Some(next_signal)
        } else {
            None
        }
    }
}
impl Signal {
    pub fn iterator() -> SignalIterator {
        SignalIterator{next: 0}
    }
    
    
    
    #[inline]
    pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
        if 0 < signum && signum < NSIG {
            Ok(unsafe { mem::transmute(signum) })
        } else {
            Err(Error::invalid_argument())
        }
    }
}
pub const SIGIOT : Signal = SIGABRT;
pub const SIGPOLL : Signal = SIGIO;
pub const SIGUNUSED : Signal = SIGSYS;
libc_bitflags!{
    pub struct SaFlags: libc::c_int {
        SA_NOCLDSTOP;
        SA_NOCLDWAIT;
        SA_NODEFER;
        SA_ONSTACK;
        SA_RESETHAND;
        SA_RESTART;
        SA_SIGINFO;
    }
}
libc_enum! {
    #[repr(i32)]
    pub enum SigmaskHow {
        SIG_BLOCK,
        SIG_UNBLOCK,
        SIG_SETMASK,
    }
}
#[derive(Clone, Copy)]
#[allow(missing_debug_implementations)]
pub struct SigSet {
    sigset: libc::sigset_t
}
impl SigSet {
    pub fn all() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };
        SigSet { sigset: sigset }
    }
    pub fn empty() -> SigSet {
        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };
        SigSet { sigset: sigset }
    }
    pub fn add(&mut self, signal: Signal) {
        unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
    }
    pub fn clear(&mut self) {
        unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
    }
    pub fn remove(&mut self, signal: Signal) {
        unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
    }
    pub fn contains(&self, signal: Signal) -> bool {
        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
        match res {
            1 => true,
            0 => false,
            _ => unreachable!("unexpected value from sigismember"),
        }
    }
    pub fn extend(&mut self, other: &SigSet) {
        for signal in Signal::iterator() {
            if other.contains(signal) {
                self.add(signal);
            }
        }
    }
    
    pub fn thread_get_mask() -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))?;
        Ok(oldmask)
    }
    
    pub fn thread_set_mask(&self) -> Result<()> {
        pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
    }
    
    pub fn thread_block(&self) -> Result<()> {
        pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
    }
    
    pub fn thread_unblock(&self) -> Result<()> {
        pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
    }
    
    pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
        pthread_sigmask(how, Some(self), Some(&mut oldmask))?;
        Ok(oldmask)
    }
    
    
    pub fn wait(&self) -> Result<Signal> {
        let mut signum: libc::c_int = unsafe { mem::uninitialized() };
        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
        Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
    }
}
impl AsRef<libc::sigset_t> for SigSet {
    fn as_ref(&self) -> &libc::sigset_t {
        &self.sigset
    }
}
#[allow(unknown_lints)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SigHandler {
    
    SigDfl,
    
    SigIgn,
    
    Handler(extern fn(libc::c_int)),
    
    
    SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
}
#[derive(Clone, Copy)]
#[allow(missing_debug_implementations)]
pub struct SigAction {
    sigaction: libc::sigaction
}
impl SigAction {
    
    
    
    
    
    pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
        s.sa_sigaction = match handler {
            SigHandler::SigDfl => libc::SIG_DFL,
            SigHandler::SigIgn => libc::SIG_IGN,
            SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
            SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
        };
        s.sa_flags = match handler {
            SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
            _ => (flags - SaFlags::SA_SIGINFO).bits(),
        };
        s.sa_mask = mask.sigset;
        SigAction { sigaction: s }
    }
    
    pub fn flags(&self) -> SaFlags {
        SaFlags::from_bits_truncate(self.sigaction.sa_flags)
    }
    
    
    pub fn mask(&self) -> SigSet {
        SigSet { sigset: self.sigaction.sa_mask }
    }
    
    pub fn handler(&self) -> SigHandler {
        match self.sigaction.sa_sigaction {
            libc::SIG_DFL => SigHandler::SigDfl,
            libc::SIG_IGN => SigHandler::SigIgn,
            f if self.flags().contains(SaFlags::SA_SIGINFO) =>
                SigHandler::SigAction( unsafe { mem::transmute(f) } ),
            f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
        }
    }
}
pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
    let mut oldact = mem::uninitialized::<libc::sigaction>();
    let res =
        libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
    Errno::result(res).map(|_| SigAction { sigaction: oldact })
}
pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
    let signal = signal as libc::c_int;
    let res = match handler {
        SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
        SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
        SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
        SigHandler::SigAction(_) => return Err(Error::UnsupportedOperation),
    };
    Errno::result(res).map(|oldhandler| {
        match oldhandler {
            libc::SIG_DFL => SigHandler::SigDfl,
            libc::SIG_IGN => SigHandler::SigIgn,
            f => SigHandler::Handler(mem::transmute(f)),
        }
    })
}
pub fn pthread_sigmask(how: SigmaskHow,
                       set: Option<&SigSet>,
                       oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }
    let res = unsafe {
        
        libc::pthread_sigmask(how as libc::c_int,
                             set.map_or_else(ptr::null::<libc::sigset_t>,
                                             |s| &s.sigset as *const libc::sigset_t),
                             oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
                                                |os| &mut os.sigset as *mut libc::sigset_t))
    };
    Errno::result(res).map(drop)
}
pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
    if set.is_none() && oldset.is_none() {
        return Ok(())
    }
    let res = unsafe {
        
        libc::sigprocmask(how as libc::c_int,
                          set.map_or_else(ptr::null::<libc::sigset_t>,
                                          |s| &s.sigset as *const libc::sigset_t),
                          oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
                                             |os| &mut os.sigset as *mut libc::sigset_t))
    };
    Errno::result(res).map(drop)
}
pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()> {
    let res = unsafe { libc::kill(pid.into(),
                                  match signal.into() {
                                      Some(s) => s as libc::c_int,
                                      None => 0,
                                  }) };
    Errno::result(res).map(drop)
}
pub fn raise(signal: Signal) -> Result<()> {
    let res = unsafe { libc::raise(signal as libc::c_int) };
    Errno::result(res).map(drop)
}
#[cfg(target_os = "freebsd")]
pub type type_of_thread_id = libc::lwpid_t;
#[cfg(target_os = "linux")]
pub type type_of_thread_id = libc::pid_t;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SigevNotify {
    
    SigevNone,
    
    
    
    SigevSignal { signal: Signal, si_value: libc::intptr_t },
    
    
    
    
    #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
    SigevKevent { kq: RawFd, udata: libc::intptr_t },
    
    
    
    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
    SigevThreadId { signal: Signal, thread_id: type_of_thread_id,
                    si_value: libc::intptr_t },
}
#[cfg(not(target_os = "openbsd"))]
mod sigevent {
    use libc;
    use std::mem;
    use std::ptr;
    use std::fmt::{self, Debug};
    use super::SigevNotify;
    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
    use super::type_of_thread_id;
    
    
    #[repr(C)]
    #[derive(Clone, Copy)]
    pub struct SigEvent {
        sigevent: libc::sigevent
    }
    impl SigEvent {
        
        
        
        
        
        
        
        
        
        
        
        
        
        pub fn new(sigev_notify: SigevNotify) -> SigEvent {
            let mut sev = unsafe { mem::zeroed::<libc::sigevent>()};
            sev.sigev_notify = match sigev_notify {
                SigevNotify::SigevNone => libc::SIGEV_NONE,
                SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
                SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
                #[cfg(target_os = "freebsd")]
                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
                #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
                #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
                SigevNotify::SigevThreadId{..} => 4  
            };
            sev.sigev_signo = match sigev_notify {
                SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
                SigevNotify::SigevKevent{ kq, ..} => kq,
                #[cfg(any(target_os = "linux", target_os = "freebsd"))]
                SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
                _ => 0
            };
            sev.sigev_value.sival_ptr = match sigev_notify {
                SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
                SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
                SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
                #[cfg(any(target_os = "freebsd", target_os = "linux"))]
                SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
            };
            SigEvent::set_tid(&mut sev, &sigev_notify);
            SigEvent{sigevent: sev}
        }
        #[cfg(any(target_os = "freebsd", target_os = "linux"))]
        fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
            sev.sigev_notify_thread_id = match *sigev_notify {
                SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
                _ => 0 as type_of_thread_id
            };
        }
        #[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
        fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
        }
        pub fn sigevent(&self) -> libc::sigevent {
            self.sigevent
        }
    }
    impl Debug for SigEvent {
        #[cfg(any(target_os = "freebsd", target_os = "linux"))]
        fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            fmt.debug_struct("SigEvent")
                .field("sigev_notify", &self.sigevent.sigev_notify)
                .field("sigev_signo", &self.sigevent.sigev_signo)
                .field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
                .field("sigev_notify_thread_id",
                        &self.sigevent.sigev_notify_thread_id)
                .finish()
        }
        #[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
        fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            fmt.debug_struct("SigEvent")
                .field("sigev_notify", &self.sigevent.sigev_notify)
                .field("sigev_signo", &self.sigevent.sigev_signo)
                .field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
                .finish()
        }
    }
    impl<'a> From<&'a libc::sigevent> for SigEvent {
        fn from(sigevent: &libc::sigevent) -> Self {
            SigEvent{ sigevent: *sigevent }
        }
    }
}
#[cfg(test)]
mod tests {
    use std::thread;
    use super::*;
    #[test]
    fn test_contains() {
        let mut mask = SigSet::empty();
        mask.add(SIGUSR1);
        assert!(mask.contains(SIGUSR1));
        assert!(!mask.contains(SIGUSR2));
        let all = SigSet::all();
        assert!(all.contains(SIGUSR1));
        assert!(all.contains(SIGUSR2));
    }
    #[test]
    fn test_clear() {
        let mut set = SigSet::all();
        set.clear();
        for signal in Signal::iterator() {
            assert!(!set.contains(signal));
        }
    }
    #[test]
    fn test_from_str_round_trips() {
        for signal in Signal::iterator() {
            assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
            assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
        }
    }
    #[test]
    fn test_from_str_invalid_value() {
        let errval = Err(Error::Sys(Errno::EINVAL));
        assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
        assert_eq!("kill".parse::<Signal>(), errval);
        assert_eq!("9".parse::<Signal>(), errval);
    }
    #[test]
    fn test_extend() {
        let mut one_signal = SigSet::empty();
        one_signal.add(SIGUSR1);
        let mut two_signals = SigSet::empty();
        two_signals.add(SIGUSR2);
        two_signals.extend(&one_signal);
        assert!(two_signals.contains(SIGUSR1));
        assert!(two_signals.contains(SIGUSR2));
    }
    
    #[test]
    fn test_thread_signal_get_mask() {
        assert!(SigSet::thread_get_mask().is_ok());
    }
    #[test]
    fn test_thread_signal_set_mask() {
        thread::spawn(|| {
            let prev_mask = SigSet::thread_get_mask()
                .expect("Failed to get existing signal mask!");
            let mut test_mask = prev_mask;
            test_mask.add(SIGUSR1);
            assert!(test_mask.thread_set_mask().is_ok());
            let new_mask = SigSet::thread_get_mask()
                .expect("Failed to get new mask!");
            assert!(new_mask.contains(SIGUSR1));
            assert!(!new_mask.contains(SIGUSR2));
            prev_mask.thread_set_mask().expect("Failed to revert signal mask!");
        }).join().unwrap();
    }
    #[test]
    fn test_thread_signal_block() {
        thread::spawn(|| {
            let mut mask = SigSet::empty();
            mask.add(SIGUSR1);
            assert!(mask.thread_block().is_ok());
            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
        }).join().unwrap();
    }
    #[test]
    fn test_thread_signal_unblock() {
        thread::spawn(|| {
            let mut mask = SigSet::empty();
            mask.add(SIGUSR1);
            assert!(mask.thread_unblock().is_ok());
            assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
        }).join().unwrap();
    }
    #[test]
    fn test_thread_signal_swap() {
        thread::spawn(|| {
            let mut mask = SigSet::empty();
            mask.add(SIGUSR1);
            mask.thread_block().unwrap();
            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
            let mut mask2 = SigSet::empty();
            mask2.add(SIGUSR2);
            let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK)
                .unwrap();
            assert!(oldmask.contains(SIGUSR1));
            assert!(!oldmask.contains(SIGUSR2));
            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
        }).join().unwrap();
    }
    #[test]
    fn test_sigaction() {
        use libc;
        thread::spawn(|| {
            extern fn test_sigaction_handler(_: libc::c_int) {}
            extern fn test_sigaction_action(_: libc::c_int,
                _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
            let handler_sig = SigHandler::Handler(test_sigaction_handler);
            let flags = SaFlags::SA_ONSTACK | SaFlags::SA_RESTART |
                        SaFlags::SA_SIGINFO;
            let mut mask = SigSet::empty();
            mask.add(SIGUSR1);
            let action_sig = SigAction::new(handler_sig, flags, mask);
            assert_eq!(action_sig.flags(),
                       SaFlags::SA_ONSTACK | SaFlags::SA_RESTART);
            assert_eq!(action_sig.handler(), handler_sig);
            mask = action_sig.mask();
            assert!(mask.contains(SIGUSR1));
            assert!(!mask.contains(SIGUSR2));
            let handler_act = SigHandler::SigAction(test_sigaction_action);
            let action_act = SigAction::new(handler_act, flags, mask);
            assert_eq!(action_act.handler(), handler_act);
            let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
            assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
            let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
            assert_eq!(action_ign.handler(), SigHandler::SigIgn);
        }).join().unwrap();
    }
    
    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
    #[test]
    fn test_sigwait() {
        thread::spawn(|| {
            let mut mask = SigSet::empty();
            mask.add(SIGUSR1);
            mask.add(SIGUSR2);
            mask.thread_block().unwrap();
            raise(SIGUSR1).unwrap();
            assert_eq!(mask.wait().unwrap(), SIGUSR1);
        }).join().unwrap();
    }
}