1use crate::errno::Errno;
7use crate::{Error, Result};
8use cfg_if::cfg_if;
9use std::fmt;
10use std::hash::{Hash, Hasher};
11use std::mem;
12use std::ops::BitOr;
13#[cfg(freebsdlike)]
14use std::os::unix::io::RawFd;
15use std::ptr;
16use std::str::FromStr;
17
18#[cfg(not(any(
19    target_os = "fuchsia",
20    target_os = "hurd",
21    target_os = "openbsd",
22    target_os = "redox"
23)))]
24#[cfg(any(feature = "aio", feature = "signal"))]
25pub use self::sigevent::*;
26
27#[cfg(any(feature = "aio", feature = "process", feature = "signal"))]
28libc_enum! {
29    #[repr(i32)]
35    #[non_exhaustive]
36    #[cfg_attr(docsrs, doc(cfg(any(feature = "aio", feature = "signal"))))]
37    pub enum Signal {
38        SIGHUP,
40        SIGINT,
42        SIGQUIT,
44        SIGILL,
46        SIGTRAP,
48        SIGABRT,
50        SIGBUS,
52        SIGFPE,
54        SIGKILL,
56        SIGUSR1,
58        SIGSEGV,
60        SIGUSR2,
62        SIGPIPE,
64        SIGALRM,
66        SIGTERM,
68        #[cfg(all(any(linux_android, target_os = "emscripten",
70                      target_os = "fuchsia"),
71                  not(any(target_arch = "mips",
72                          target_arch = "mips32r6",
73                          target_arch = "mips64",
74                          target_arch = "mips64r6",
75                          target_arch = "sparc64"))))]
76        SIGSTKFLT,
77        SIGCHLD,
79        SIGCONT,
81        SIGSTOP,
83        SIGTSTP,
85        SIGTTIN,
87        SIGTTOU,
89        SIGURG,
91        SIGXCPU,
93        SIGXFSZ,
95        SIGVTALRM,
97        SIGPROF,
99        SIGWINCH,
101        #[cfg(not(target_os = "haiku"))]
103        SIGIO,
104        #[cfg(any(linux_android, target_os = "emscripten",
105                  target_os = "fuchsia", target_os = "aix"))]
106        SIGPWR,
108        SIGSYS,
110        #[cfg(not(any(linux_android, target_os = "emscripten",
111                      target_os = "fuchsia",
112                      target_os = "redox", target_os = "haiku")))]
113        SIGEMT,
115        #[cfg(not(any(linux_android, target_os = "emscripten",
116                      target_os = "fuchsia", target_os = "redox",
117                      target_os = "haiku", target_os = "aix")))]
118        SIGINFO,
120    }
121    impl TryFrom<i32>
122}
123
124#[cfg(feature = "signal")]
125impl FromStr for Signal {
126    type Err = Error;
127    fn from_str(s: &str) -> Result<Signal> {
128        Ok(match s {
129            "SIGHUP" => Signal::SIGHUP,
130            "SIGINT" => Signal::SIGINT,
131            "SIGQUIT" => Signal::SIGQUIT,
132            "SIGILL" => Signal::SIGILL,
133            "SIGTRAP" => Signal::SIGTRAP,
134            "SIGABRT" => Signal::SIGABRT,
135            "SIGBUS" => Signal::SIGBUS,
136            "SIGFPE" => Signal::SIGFPE,
137            "SIGKILL" => Signal::SIGKILL,
138            "SIGUSR1" => Signal::SIGUSR1,
139            "SIGSEGV" => Signal::SIGSEGV,
140            "SIGUSR2" => Signal::SIGUSR2,
141            "SIGPIPE" => Signal::SIGPIPE,
142            "SIGALRM" => Signal::SIGALRM,
143            "SIGTERM" => Signal::SIGTERM,
144            #[cfg(all(
145                any(
146                    linux_android,
147                    target_os = "emscripten",
148                    target_os = "fuchsia",
149                ),
150                not(any(
151                    target_arch = "mips",
152                    target_arch = "mips32r6",
153                    target_arch = "mips64",
154                    target_arch = "mips64r6",
155                    target_arch = "sparc64"
156                ))
157            ))]
158            "SIGSTKFLT" => Signal::SIGSTKFLT,
159            "SIGCHLD" => Signal::SIGCHLD,
160            "SIGCONT" => Signal::SIGCONT,
161            "SIGSTOP" => Signal::SIGSTOP,
162            "SIGTSTP" => Signal::SIGTSTP,
163            "SIGTTIN" => Signal::SIGTTIN,
164            "SIGTTOU" => Signal::SIGTTOU,
165            "SIGURG" => Signal::SIGURG,
166            "SIGXCPU" => Signal::SIGXCPU,
167            "SIGXFSZ" => Signal::SIGXFSZ,
168            "SIGVTALRM" => Signal::SIGVTALRM,
169            "SIGPROF" => Signal::SIGPROF,
170            "SIGWINCH" => Signal::SIGWINCH,
171            #[cfg(not(target_os = "haiku"))]
172            "SIGIO" => Signal::SIGIO,
173            #[cfg(any(
174                linux_android,
175                target_os = "emscripten",
176                target_os = "fuchsia",
177            ))]
178            "SIGPWR" => Signal::SIGPWR,
179            "SIGSYS" => Signal::SIGSYS,
180            #[cfg(not(any(
181                linux_android,
182                target_os = "emscripten",
183                target_os = "fuchsia",
184                target_os = "redox",
185                target_os = "haiku"
186            )))]
187            "SIGEMT" => Signal::SIGEMT,
188            #[cfg(not(any(
189                linux_android,
190                target_os = "emscripten",
191                target_os = "fuchsia",
192                target_os = "redox",
193                target_os = "aix",
194                target_os = "haiku"
195            )))]
196            "SIGINFO" => Signal::SIGINFO,
197            _ => return Err(Errno::EINVAL),
198        })
199    }
200}
201
202#[cfg(feature = "signal")]
203impl Signal {
204    pub const fn as_str(self) -> &'static str {
210        match self {
211            Signal::SIGHUP => "SIGHUP",
212            Signal::SIGINT => "SIGINT",
213            Signal::SIGQUIT => "SIGQUIT",
214            Signal::SIGILL => "SIGILL",
215            Signal::SIGTRAP => "SIGTRAP",
216            Signal::SIGABRT => "SIGABRT",
217            Signal::SIGBUS => "SIGBUS",
218            Signal::SIGFPE => "SIGFPE",
219            Signal::SIGKILL => "SIGKILL",
220            Signal::SIGUSR1 => "SIGUSR1",
221            Signal::SIGSEGV => "SIGSEGV",
222            Signal::SIGUSR2 => "SIGUSR2",
223            Signal::SIGPIPE => "SIGPIPE",
224            Signal::SIGALRM => "SIGALRM",
225            Signal::SIGTERM => "SIGTERM",
226            #[cfg(all(
227                any(
228                    linux_android,
229                    target_os = "emscripten",
230                    target_os = "fuchsia",
231                ),
232                not(any(
233                    target_arch = "mips",
234                    target_arch = "mips32r6",
235                    target_arch = "mips64",
236                    target_arch = "mips64r6",
237                    target_arch = "sparc64"
238                ))
239            ))]
240            Signal::SIGSTKFLT => "SIGSTKFLT",
241            Signal::SIGCHLD => "SIGCHLD",
242            Signal::SIGCONT => "SIGCONT",
243            Signal::SIGSTOP => "SIGSTOP",
244            Signal::SIGTSTP => "SIGTSTP",
245            Signal::SIGTTIN => "SIGTTIN",
246            Signal::SIGTTOU => "SIGTTOU",
247            Signal::SIGURG => "SIGURG",
248            Signal::SIGXCPU => "SIGXCPU",
249            Signal::SIGXFSZ => "SIGXFSZ",
250            Signal::SIGVTALRM => "SIGVTALRM",
251            Signal::SIGPROF => "SIGPROF",
252            Signal::SIGWINCH => "SIGWINCH",
253            #[cfg(not(target_os = "haiku"))]
254            Signal::SIGIO => "SIGIO",
255            #[cfg(any(
256                linux_android,
257                target_os = "emscripten",
258                target_os = "fuchsia",
259                target_os = "aix",
260            ))]
261            Signal::SIGPWR => "SIGPWR",
262            Signal::SIGSYS => "SIGSYS",
263            #[cfg(not(any(
264                linux_android,
265                target_os = "emscripten",
266                target_os = "fuchsia",
267                target_os = "redox",
268                target_os = "haiku"
269            )))]
270            Signal::SIGEMT => "SIGEMT",
271            #[cfg(not(any(
272                linux_android,
273                target_os = "emscripten",
274                target_os = "fuchsia",
275                target_os = "redox",
276                target_os = "aix",
277                target_os = "haiku"
278            )))]
279            Signal::SIGINFO => "SIGINFO",
280        }
281    }
282}
283
284#[cfg(feature = "signal")]
285impl AsRef<str> for Signal {
286    fn as_ref(&self) -> &str {
287        self.as_str()
288    }
289}
290
291#[cfg(feature = "signal")]
292impl fmt::Display for Signal {
293    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
294        f.write_str(self.as_ref())
295    }
296}
297
298#[cfg(feature = "signal")]
299pub use self::Signal::*;
300
301#[cfg(target_os = "redox")]
302#[cfg(feature = "signal")]
303const SIGNALS: [Signal; 29] = [
304    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
305    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
306    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
307    SIGPROF, SIGWINCH, SIGIO, SIGSYS,
308];
309#[cfg(target_os = "haiku")]
310#[cfg(feature = "signal")]
311const SIGNALS: [Signal; 28] = [
312    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
313    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
314    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
315    SIGPROF, SIGWINCH, SIGSYS,
316];
317#[cfg(all(
318    any(linux_android, target_os = "emscripten", target_os = "fuchsia"),
319    not(any(
320        target_arch = "mips",
321        target_arch = "mips32r6",
322        target_arch = "mips64",
323        target_arch = "mips64r6",
324        target_arch = "sparc64"
325    ))
326))]
327#[cfg(feature = "signal")]
328const SIGNALS: [Signal; 31] = [
329    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
330    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGSTKFLT, SIGCHLD,
331    SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ,
332    SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
333];
334#[cfg(all(
335    any(linux_android, target_os = "emscripten", target_os = "fuchsia"),
336    any(
337        target_arch = "mips",
338        target_arch = "mips32r6",
339        target_arch = "mips64",
340        target_arch = "mips64r6",
341        target_arch = "sparc64"
342    )
343))]
344#[cfg(feature = "signal")]
345const SIGNALS: [Signal; 30] = [
346    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
347    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
348    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
349    SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
350];
351#[cfg(target_os = "aix")]
352#[cfg(feature = "signal")]
353const SIGNALS: [Signal; 30] = [
354    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGEMT, SIGFPE, SIGKILL, SIGSEGV,
355    SIGSYS, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, SIGUSR2, SIGPWR, SIGWINCH,
356    SIGURG, SIGPOLL, SIGIO, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU,
357    SIGVTALRM, SIGPROF, SIGXCPU, SIGXFSZ, SIGTRAP,
358];
359#[cfg(not(any(
360    linux_android,
361    target_os = "fuchsia",
362    target_os = "emscripten",
363    target_os = "aix",
364    target_os = "redox",
365    target_os = "haiku"
366)))]
367#[cfg(feature = "signal")]
368const SIGNALS: [Signal; 31] = [
369    SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
370    SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
371    SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
372    SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT, SIGINFO,
373];
374
375feature! {
376#![feature = "signal"]
377
378#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
379pub struct SignalIterator {
381    next: usize,
382}
383
384impl Iterator for SignalIterator {
385    type Item = Signal;
386
387    fn next(&mut self) -> Option<Signal> {
388        if self.next < SIGNALS.len() {
389            let next_signal = SIGNALS[self.next];
390            self.next += 1;
391            Some(next_signal)
392        } else {
393            None
394        }
395    }
396}
397
398impl Signal {
399    pub const fn iterator() -> SignalIterator {
401        SignalIterator{next: 0}
402    }
403}
404
405pub const SIGIOT : Signal = SIGABRT;
407#[cfg(not(target_os = "haiku"))]
409pub const SIGPOLL : Signal = SIGIO;
410pub const SIGUNUSED : Signal = SIGSYS;
412
413cfg_if! {
414    if #[cfg(target_os = "redox")] {
415        type SaFlags_t = libc::c_ulong;
416    } else if #[cfg(target_env = "uclibc")] {
417        type SaFlags_t = libc::c_ulong;
418    } else {
419        type SaFlags_t = libc::c_int;
420    }
421}
422}
423
424#[cfg(feature = "signal")]
425libc_bitflags! {
426    #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
428    pub struct SaFlags: SaFlags_t {
429        SA_NOCLDSTOP;
433        #[cfg(not(target_os = "hurd"))]
436        SA_NOCLDWAIT;
437        SA_NODEFER;
440        SA_ONSTACK;
443        SA_RESETHAND;
446        SA_RESTART;
449        SA_SIGINFO;
451    }
452}
453
454#[cfg(feature = "signal")]
455libc_enum! {
456    #[repr(i32)]
458    #[non_exhaustive]
459    #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
460    pub enum SigmaskHow {
461        SIG_BLOCK,
463        SIG_UNBLOCK,
466        SIG_SETMASK,
468    }
469}
470
471feature! {
472#![feature = "signal"]
473
474use crate::unistd::Pid;
475use std::iter::Extend;
476use std::iter::FromIterator;
477use std::iter::IntoIterator;
478
479#[repr(transparent)]
483#[derive(Clone, Copy, Debug, Eq)]
484pub struct SigSet {
485    sigset: libc::sigset_t
486}
487
488impl SigSet {
489    #[doc(alias("sigfillset"))]
491    pub fn all() -> SigSet {
492        let mut sigset = mem::MaybeUninit::uninit();
493        let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
494
495        unsafe{ SigSet { sigset: sigset.assume_init() } }
496    }
497
498    #[doc(alias("sigemptyset"))]
500    pub fn empty() -> SigSet {
501        let mut sigset = mem::MaybeUninit::uninit();
502        let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
503
504        unsafe{ SigSet { sigset: sigset.assume_init() } }
505    }
506
507    #[doc(alias("sigaddset"))]
509    pub fn add(&mut self, signal: Signal) {
510        unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
511    }
512
513    #[doc(alias("sigemptyset"))]
515    pub fn clear(&mut self) {
516        unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
517    }
518
519    #[doc(alias("sigdelset"))]
521    pub fn remove(&mut self, signal: Signal) {
522        unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
523    }
524
525    #[doc(alias("sigismember"))]
527    pub fn contains(&self, signal: Signal) -> bool {
528        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
529
530        match res {
531            1 => true,
532            0 => false,
533            _ => unreachable!("unexpected value from sigismember"),
534        }
535    }
536
537    pub fn iter(&self) -> SigSetIter<'_> {
539        self.into_iter()
540    }
541
542    pub fn thread_get_mask() -> Result<SigSet> {
544        let mut oldmask = mem::MaybeUninit::uninit();
545        do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
546        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
547    }
548
549    pub fn thread_set_mask(&self) -> Result<()> {
551        pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
552    }
553
554    pub fn thread_block(&self) -> Result<()> {
556        pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
557    }
558
559    pub fn thread_unblock(&self) -> Result<()> {
561        pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
562    }
563
564    pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
566        let mut oldmask = mem::MaybeUninit::uninit();
567        do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
568        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
569    }
570
571    #[cfg(not(target_os = "redox"))] pub fn wait(&self) -> Result<Signal> {
575        use std::convert::TryFrom;
576
577        let mut signum = mem::MaybeUninit::uninit();
578        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
579
580        Errno::result(res).map(|_| unsafe {
581            Signal::try_from(signum.assume_init()).unwrap()
582        })
583    }
584
585    #[cfg(any(
594        bsd,
595        linux_android,
596        solarish,
597        target_os = "haiku",
598        target_os = "hurd",
599        target_os = "aix",
600        target_os = "fuchsia"
601    ))]
602    #[doc(alias("sigsuspend"))]
603    pub fn suspend(&self) -> Result<()> {
604        let res = unsafe {
605            libc::sigsuspend(&self.sigset as *const libc::sigset_t)
606        };
607        match Errno::result(res).map(drop) {
608            Err(Errno::EINTR) => Ok(()),
609            Err(e) => Err(e),
610            Ok(_) => unreachable!("because this syscall always returns -1 if returns"),
611        }
612    }
613
614    pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet {
624        SigSet { sigset }
625    }
626}
627
628impl From<Signal> for SigSet {
629    fn from(signal: Signal) -> SigSet {
630        let mut sigset = SigSet::empty();
631        sigset.add(signal);
632        sigset
633    }
634}
635
636impl BitOr for Signal {
637    type Output = SigSet;
638
639    fn bitor(self, rhs: Self) -> Self::Output {
640        let mut sigset = SigSet::empty();
641        sigset.add(self);
642        sigset.add(rhs);
643        sigset
644    }
645}
646
647impl BitOr<Signal> for SigSet {
648    type Output = SigSet;
649
650    fn bitor(mut self, rhs: Signal) -> Self::Output {
651        self.add(rhs);
652        self
653    }
654}
655
656impl BitOr for SigSet {
657    type Output = Self;
658
659    fn bitor(self, rhs: Self) -> Self::Output {
660        self.iter().chain(rhs.iter()).collect()
661    }
662}
663
664impl AsRef<libc::sigset_t> for SigSet {
665    fn as_ref(&self) -> &libc::sigset_t {
666        &self.sigset
667    }
668}
669
670impl Extend<Signal> for SigSet {
672    fn extend<T>(&mut self, iter: T)
673    where T: IntoIterator<Item = Signal> {
674        for signal in iter {
675            self.add(signal);
676        }
677    }
678}
679
680impl FromIterator<Signal> for SigSet {
681    fn from_iter<T>(iter: T) -> Self
682    where T: IntoIterator<Item = Signal> {
683        let mut sigset = SigSet::empty();
684        sigset.extend(iter);
685        sigset
686    }
687}
688
689impl PartialEq for SigSet {
690    fn eq(&self, other: &Self) -> bool {
691        for signal in Signal::iterator() {
692            if self.contains(signal) != other.contains(signal) {
693                return false;
694            }
695        }
696        true
697    }
698}
699
700impl Hash for SigSet {
701    fn hash<H: Hasher>(&self, state: &mut H) {
702        for signal in Signal::iterator() {
703            if self.contains(signal) {
704                signal.hash(state);
705            }
706        }
707    }
708}
709
710#[derive(Clone, Debug)]
714pub struct SigSetIter<'a> {
715    sigset: &'a SigSet,
716    inner: SignalIterator,
717}
718
719impl Iterator for SigSetIter<'_> {
720    type Item = Signal;
721    fn next(&mut self) -> Option<Signal> {
722        loop {
723            match self.inner.next() {
724                None => return None,
725                Some(signal) if self.sigset.contains(signal) => return Some(signal),
726                Some(_signal) => continue,
727            }
728        }
729    }
730}
731
732impl<'a> IntoIterator for &'a SigSet {
733    type Item = Signal;
734    type IntoIter = SigSetIter<'a>;
735    fn into_iter(self) -> Self::IntoIter {
736        SigSetIter { sigset: self, inner: Signal::iterator() }
737    }
738}
739
740#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
742pub enum SigHandler {
743    SigDfl,
745    SigIgn,
747    Handler(extern fn(libc::c_int)),
749    #[cfg(not(target_os = "redox"))]
752    SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
753}
754
755#[repr(transparent)]
757#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
758pub struct SigAction {
759    sigaction: libc::sigaction
760}
761
762impl From<SigAction> for libc::sigaction {
763    fn from(value: SigAction) -> libc::sigaction {
764        value.sigaction
765    }
766}
767
768impl SigAction {
769    pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
775        #[cfg(not(target_os = "aix"))]
776        unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
777            unsafe {
778                 (*p).sa_sigaction = match handler {
779                    SigHandler::SigDfl => libc::SIG_DFL,
780                    SigHandler::SigIgn => libc::SIG_IGN,
781                    SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
782                    #[cfg(not(target_os = "redox"))]
783                    SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
784                };
785            }
786        }
787
788        #[cfg(target_os = "aix")]
789        unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
790            unsafe {
791                (*p).sa_union.__su_sigaction = match handler {
792                    SigHandler::SigDfl => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL) },
793                    SigHandler::SigIgn => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN) },
794                    SigHandler::Handler(f) => unsafe { mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f) },
795                    SigHandler::SigAction(f) => f,
796                };
797            }
798        }
799
800        let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
801        unsafe {
802            let p = s.as_mut_ptr();
803            install_sig(p, handler);
804            (*p).sa_flags = match handler {
805                #[cfg(not(target_os = "redox"))]
806                SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
807                _ => (flags - SaFlags::SA_SIGINFO).bits(),
808            };
809            (*p).sa_mask = mask.sigset;
810
811            SigAction { sigaction: s.assume_init() }
812        }
813    }
814
815    pub fn flags(&self) -> SaFlags {
817        SaFlags::from_bits_truncate(self.sigaction.sa_flags)
818    }
819
820    pub fn mask(&self) -> SigSet {
823        SigSet { sigset: self.sigaction.sa_mask }
824    }
825
826    #[cfg(not(target_os = "aix"))]
828    pub fn handler(&self) -> SigHandler {
829        match self.sigaction.sa_sigaction {
830            libc::SIG_DFL => SigHandler::SigDfl,
831            libc::SIG_IGN => SigHandler::SigIgn,
832            #[cfg(not(target_os = "redox"))]
833            p if self.flags().contains(SaFlags::SA_SIGINFO) =>
834                SigHandler::SigAction(
835                unsafe{
842                    *(&p as *const usize
843                         as *const extern fn(_, _, _))
844                }
845                as extern fn(_, _, _)),
846            p => SigHandler::Handler(
847                unsafe{
854                    *(&p as *const usize
855                         as *const extern fn(libc::c_int))
856                }
857                as extern fn(libc::c_int)),
858        }
859    }
860
861    #[cfg(target_os = "aix")]
863    pub fn handler(&self) -> SigHandler {
864        unsafe {
865        match self.sigaction.sa_union.__su_sigaction as usize {
866            libc::SIG_DFL => SigHandler::SigDfl,
867            libc::SIG_IGN => SigHandler::SigIgn,
868            p if self.flags().contains(SaFlags::SA_SIGINFO) =>
869                SigHandler::SigAction(
870                    *(&p as *const usize
871                         as *const extern fn(_, _, _))
872                as extern fn(_, _, _)),
873            p => SigHandler::Handler(
874                    *(&p as *const usize
875                         as *const extern fn(libc::c_int))
876                as extern fn(libc::c_int)),
877        }
878        }
879    }
880}
881
882pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
900    let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
901
902    let res = unsafe { libc::sigaction(signal as libc::c_int,
903                              &sigaction.sigaction as *const libc::sigaction,
904                              oldact.as_mut_ptr()) };
905
906    Errno::result(res).map(|_| SigAction { sigaction: unsafe { oldact.assume_init() } })
907}
908
909pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
962    let signal = signal as libc::c_int;
963    let res = match handler {
964        SigHandler::SigDfl => unsafe { libc::signal(signal, libc::SIG_DFL) },
965        SigHandler::SigIgn => unsafe { libc::signal(signal, libc::SIG_IGN) },
966        SigHandler::Handler(handler) => unsafe { libc::signal(signal, handler as libc::sighandler_t) },
967        #[cfg(not(target_os = "redox"))]
968        SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
969    };
970    Errno::result(res).map(|oldhandler| {
971        match oldhandler {
972            libc::SIG_DFL => SigHandler::SigDfl,
973            libc::SIG_IGN => SigHandler::SigIgn,
974            p => SigHandler::Handler(
975                unsafe { *(&p as *const usize as *const extern fn(libc::c_int)) } as extern fn(libc::c_int)),
976        }
977    })
978}
979
980fn do_pthread_sigmask(how: SigmaskHow,
981                       set: Option<&SigSet>,
982                       oldset: Option<*mut libc::sigset_t>) -> Result<()> {
983    if set.is_none() && oldset.is_none() {
984        return Ok(())
985    }
986
987    let res = unsafe {
988        libc::pthread_sigmask(how as libc::c_int,
990                             set.map_or_else(ptr::null::<libc::sigset_t>,
991                                             |s| &s.sigset as *const libc::sigset_t),
992                             oldset.unwrap_or(ptr::null_mut())
993                             )
994    };
995
996    Errno::result(res).map(drop)
997}
998
999pub fn pthread_sigmask(how: SigmaskHow,
1015                       set: Option<&SigSet>,
1016                       oldset: Option<&mut SigSet>) -> Result<()>
1017{
1018    do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
1019}
1020
1021pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
1026    if set.is_none() && oldset.is_none() {
1027        return Ok(())
1028    }
1029
1030    let res = unsafe {
1031        libc::sigprocmask(how as libc::c_int,
1033                          set.map_or_else(ptr::null::<libc::sigset_t>,
1034                                          |s| &s.sigset as *const libc::sigset_t),
1035                          oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
1036                                             |os| &mut os.sigset as *mut libc::sigset_t))
1037    };
1038
1039    Errno::result(res).map(drop)
1040}
1041
1042#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
1051#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
1052pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
1062    let res = unsafe { libc::kill(pid.into(),
1063                                  match signal.into() {
1064                                      Some(s) => s as libc::c_int,
1065                                      None => 0,
1066                                  }) };
1067
1068    Errno::result(res).map(drop)
1069}
1070
1071#[cfg(not(target_os = "fuchsia"))]
1082pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
1083    let res = unsafe { libc::killpg(pgrp.into(),
1084                                  match signal.into() {
1085                                      Some(s) => s as libc::c_int,
1086                                      None => 0,
1087                                  }) };
1088
1089    Errno::result(res).map(drop)
1090}
1091
1092pub fn raise(signal: Signal) -> Result<()> {
1096    let res = unsafe { libc::raise(signal as libc::c_int) };
1097
1098    Errno::result(res).map(drop)
1099}
1100}
1101
1102feature! {
1103#![any(feature = "aio", feature = "signal")]
1104
1105#[cfg(target_os = "freebsd")]
1107pub type type_of_thread_id = libc::lwpid_t;
1108#[cfg(all(not(target_os = "hurd"), any(target_env = "gnu", target_env = "uclibc")))]
1110pub type type_of_thread_id = libc::pid_t;
1111
1112#[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))]
1117#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1118pub enum SigevNotify {
1119    SigevNone,
1121    SigevSignal {
1123        signal: Signal,
1125        si_value: libc::intptr_t
1128    },
1129    #[cfg(freebsdlike)]
1132    SigevKevent {
1133        kq: RawFd,
1135        udata: libc::intptr_t
1137    },
1138    #[cfg(target_os = "freebsd")]
1140    #[cfg(feature = "event")]
1141    SigevKeventFlags {
1142        kq: RawFd,
1144        udata: libc::intptr_t,
1146        flags: crate::sys::event::EventFlag
1148    },
1149    #[cfg(any(
1151            target_os = "freebsd",
1152            target_env = "gnu",
1153            target_env = "uclibc",
1154    ))]
1155    SigevThreadId {
1156        signal: Signal,
1158        thread_id: type_of_thread_id,
1160        si_value: libc::intptr_t
1163    },
1164}
1165}
1166
1167#[cfg(not(any(
1168    target_os = "fuchsia",
1169    target_os = "hurd",
1170    target_os = "openbsd",
1171    target_os = "redox"
1172)))]
1173mod sigevent {
1174    feature! {
1175    #![any(feature = "aio", feature = "signal")]
1176
1177    use std::mem;
1178    use super::SigevNotify;
1179
1180    #[cfg(target_os = "freebsd")]
1181    pub(crate) use ffi::sigevent as libc_sigevent;
1182    #[cfg(not(target_os = "freebsd"))]
1183    pub(crate) use libc::sigevent as libc_sigevent;
1184
1185    #[cfg(target_os = "freebsd")]
1197    mod ffi {
1198        use std::{fmt, hash};
1199
1200        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1201        #[repr(C)]
1202        pub struct __c_anonymous_sigev_thread {
1203            pub _function: *mut libc::c_void,   pub _attribute: *mut libc::pthread_attr_t,
1205        }
1206        #[derive(Clone, Copy)]
1207        #[allow(missing_debug_implementations)]
1210        #[repr(C)]
1211        pub union __c_anonymous_sigev_un {
1212            pub _threadid: libc::__lwpid_t,
1213            pub _sigev_thread: __c_anonymous_sigev_thread,
1214            pub _kevent_flags: libc::c_ushort,
1215            __spare__: [libc::c_long; 8],
1216        }
1217
1218        #[derive(Clone, Copy)]
1219        #[repr(C)]
1220        pub struct sigevent {
1221            pub sigev_notify: libc::c_int,
1222            pub sigev_signo: libc::c_int,
1223            pub sigev_value: libc::sigval,
1224            pub _sigev_un: __c_anonymous_sigev_un,
1225        }
1226
1227        impl fmt::Debug for sigevent {
1228            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1229                let mut ds = f.debug_struct("sigevent");
1230                ds.field("sigev_notify", &self.sigev_notify)
1231                    .field("sigev_signo", &self.sigev_signo)
1232                    .field("sigev_value", &self.sigev_value);
1233                unsafe {
1235                    match self.sigev_notify {
1236                        libc::SIGEV_KEVENT => {
1237                            ds.field("sigev_notify_kevent_flags", &self._sigev_un._kevent_flags);
1238                        }
1239                        libc::SIGEV_THREAD_ID => {
1240                            ds.field("sigev_notify_thread_id", &self._sigev_un._threadid);
1241                        }
1242                        libc::SIGEV_THREAD => {
1243                            ds.field("sigev_notify_function", &self._sigev_un._sigev_thread._function);
1244                            ds.field("sigev_notify_attributes", &self._sigev_un._sigev_thread._attribute);
1245                        }
1246                        _ => ()
1247                    };
1248                }
1249                ds.finish()
1250            }
1251        }
1252
1253        impl PartialEq for sigevent {
1254            fn eq(&self, other: &Self) -> bool {
1255                let mut equals = self.sigev_notify == other.sigev_notify;
1256                equals &= self.sigev_signo == other.sigev_signo;
1257                equals &= self.sigev_value == other.sigev_value;
1258                unsafe {
1260                    match self.sigev_notify {
1261                        libc::SIGEV_KEVENT => {
1262                            equals &= self._sigev_un._kevent_flags == other._sigev_un._kevent_flags;
1263                        }
1264                        libc::SIGEV_THREAD_ID => {
1265                            equals &= self._sigev_un._threadid == other._sigev_un._threadid;
1266                        }
1267                        libc::SIGEV_THREAD => {
1268                            equals &= self._sigev_un._sigev_thread == other._sigev_un._sigev_thread;
1269                        }
1270                        _ => ()
1271                    }
1272                }
1273                equals
1274            }
1275        }
1276
1277        impl Eq for sigevent {}
1278
1279        impl hash::Hash for sigevent {
1280            fn hash<H: hash::Hasher>(&self, s: &mut H) {
1281                self.sigev_notify.hash(s);
1282                self.sigev_signo.hash(s);
1283                self.sigev_value.hash(s);
1284                unsafe {
1286                    match self.sigev_notify {
1287                        libc::SIGEV_KEVENT => {
1288                            self._sigev_un._kevent_flags.hash(s);
1289                        }
1290                        libc::SIGEV_THREAD_ID => {
1291                            self._sigev_un._threadid.hash(s);
1292                        }
1293                        libc::SIGEV_THREAD => {
1294                            self._sigev_un._sigev_thread.hash(s);
1295                        }
1296                        _ => ()
1297                    }
1298                }
1299            }
1300        }
1301    }
1302
1303    #[repr(C)]
1306    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1307    #[allow(missing_copy_implementations)]
1309    pub struct SigEvent {
1310        sigevent: libc_sigevent
1311    }
1312
1313    impl SigEvent {
1314        pub fn new(sigev_notify: SigevNotify) -> SigEvent {
1328            let mut sev: libc_sigevent = unsafe { mem::zeroed() };
1329            match sigev_notify {
1330                SigevNotify::SigevNone => {
1331                    sev.sigev_notify = libc::SIGEV_NONE;
1332                },
1333                SigevNotify::SigevSignal{signal, si_value} => {
1334                    sev.sigev_notify = libc::SIGEV_SIGNAL;
1335                    sev.sigev_signo = signal as libc::c_int;
1336                    sev.sigev_value.sival_ptr = si_value as *mut libc::c_void
1337                },
1338                #[cfg(freebsdlike)]
1339                SigevNotify::SigevKevent{kq, udata} => {
1340                    sev.sigev_notify = libc::SIGEV_KEVENT;
1341                    sev.sigev_signo = kq;
1342                    sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
1343                },
1344                #[cfg(target_os = "freebsd")]
1345                #[cfg(feature = "event")]
1346                SigevNotify::SigevKeventFlags{kq, udata, flags} => {
1347                    sev.sigev_notify = libc::SIGEV_KEVENT;
1348                    sev.sigev_signo = kq;
1349                    sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
1350                    sev._sigev_un._kevent_flags = flags.bits();
1351                },
1352                #[cfg(target_os = "freebsd")]
1353                SigevNotify::SigevThreadId{signal, thread_id, si_value} => {
1354                    sev.sigev_notify = libc::SIGEV_THREAD_ID;
1355                    sev.sigev_signo = signal as libc::c_int;
1356                    sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
1357                    sev._sigev_un._threadid = thread_id;
1358                }
1359                #[cfg(any(target_env = "gnu", target_env = "uclibc"))]
1360                SigevNotify::SigevThreadId{signal, thread_id, si_value} => {
1361                    sev.sigev_notify = libc::SIGEV_THREAD_ID;
1362                    sev.sigev_signo = signal as libc::c_int;
1363                    sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
1364                    sev.sigev_notify_thread_id = thread_id;
1365                }
1366            }
1367            SigEvent{sigevent: sev}
1368        }
1369
1370        #[cfg(target_os = "freebsd")]
1372        pub fn sigevent(&self) -> libc::sigevent {
1373            unsafe {
1376                mem::transmute::<libc_sigevent, libc::sigevent>(self.sigevent)
1377            }
1378        }
1379
1380        #[cfg(not(target_os = "freebsd"))]
1382        pub fn sigevent(&self) -> libc::sigevent {
1383            self.sigevent
1384        }
1385
1386        #[cfg(target_os = "freebsd")]
1388        pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1389            &mut self.sigevent as *mut libc_sigevent as *mut libc::sigevent
1392        }
1393
1394        #[cfg(not(target_os = "freebsd"))]
1396        pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1397            &mut self.sigevent
1398        }
1399    }
1400
1401    impl<'a> From<&'a libc::sigevent> for SigEvent {
1402        #[cfg(target_os = "freebsd")]
1403        fn from(sigevent: &libc::sigevent) -> Self {
1404            let sigevent = unsafe {
1407                mem::transmute::<libc::sigevent, libc_sigevent>(*sigevent)
1408            };
1409            SigEvent{ sigevent }
1410        }
1411        #[cfg(not(target_os = "freebsd"))]
1412        fn from(sigevent: &libc::sigevent) -> Self {
1413            SigEvent{ sigevent: *sigevent }
1414        }
1415    }
1416    }
1417}