1 // Portions of this file are Copyright 2014 The Rust Project Developers.
2 // See https://www.rust-lang.org/policies/licenses.
3 
4 //! Operating system signals.
5 
6 use crate::errno::Errno;
7 use crate::{Error, Result};
8 use cfg_if::cfg_if;
9 use std::fmt;
10 use std::hash::{Hash, Hasher};
11 use std::mem;
12 use std::ops::BitOr;
13 #[cfg(freebsdlike)]
14 use std::os::unix::io::RawFd;
15 use std::ptr;
16 use 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"))]
25 pub use self::sigevent::*;
26 
27 #[cfg(any(feature = "aio", feature = "process", feature = "signal"))]
28 libc_enum! {
29     /// Types of operating system signals
30     // Currently there is only one definition of c_int in libc, as well as only one
31     // type for signal constants.
32     // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
33     // this is not (yet) possible.
34     #[repr(i32)]
35     #[non_exhaustive]
36     #[cfg_attr(docsrs, doc(cfg(any(feature = "aio", feature = "signal"))))]
37     pub enum Signal {
38         /// Hangup
39         SIGHUP,
40         /// Interrupt
41         SIGINT,
42         /// Quit
43         SIGQUIT,
44         /// Illegal instruction (not reset when caught)
45         SIGILL,
46         /// Trace trap (not reset when caught)
47         SIGTRAP,
48         /// Abort
49         SIGABRT,
50         /// Bus error
51         SIGBUS,
52         /// Floating point exception
53         SIGFPE,
54         /// Kill (cannot be caught or ignored)
55         SIGKILL,
56         /// User defined signal 1
57         SIGUSR1,
58         /// Segmentation violation
59         SIGSEGV,
60         /// User defined signal 2
61         SIGUSR2,
62         /// Write on a pipe with no one to read it
63         SIGPIPE,
64         /// Alarm clock
65         SIGALRM,
66         /// Software termination signal from kill
67         SIGTERM,
68         /// Stack fault (obsolete)
69         #[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         /// To parent on child stop or exit
78         SIGCHLD,
79         /// Continue a stopped process
80         SIGCONT,
81         /// Sendable stop signal not from tty
82         SIGSTOP,
83         /// Stop signal from tty
84         SIGTSTP,
85         /// To readers pgrp upon background tty read
86         SIGTTIN,
87         /// Like TTIN if (tp->t_local&LTOSTOP)
88         SIGTTOU,
89         /// Urgent condition on IO channel
90         SIGURG,
91         /// Exceeded CPU time limit
92         SIGXCPU,
93         /// Exceeded file size limit
94         SIGXFSZ,
95         /// Virtual time alarm
96         SIGVTALRM,
97         /// Profiling time alarm
98         SIGPROF,
99         /// Window size changes
100         SIGWINCH,
101         /// Input/output possible signal
102         #[cfg(not(target_os = "haiku"))]
103         SIGIO,
104         #[cfg(any(linux_android, target_os = "emscripten",
105                   target_os = "fuchsia", target_os = "aix"))]
106         /// Power failure imminent.
107         SIGPWR,
108         /// Bad system call
109         SIGSYS,
110         #[cfg(not(any(linux_android, target_os = "emscripten",
111                       target_os = "fuchsia",
112                       target_os = "redox", target_os = "haiku")))]
113         /// Emulator trap
114         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         /// Information request
119         SIGINFO,
120     }
121     impl TryFrom<i32>
122 }
123 
124 #[cfg(feature = "signal")]
125 impl FromStr for Signal {
126     type Err = Error;
from_str(s: &str) -> Result<Signal>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")]
203 impl Signal {
204     /// Returns name of signal.
205     ///
206     /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
207     /// with difference that returned string is `'static`
208     /// and not bound to `self`'s lifetime.
as_str(self) -> &'static str209     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")]
285 impl AsRef<str> for Signal {
as_ref(&self) -> &str286     fn as_ref(&self) -> &str {
287         self.as_str()
288     }
289 }
290 
291 #[cfg(feature = "signal")]
292 impl fmt::Display for Signal {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result293     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
294         f.write_str(self.as_ref())
295     }
296 }
297 
298 #[cfg(feature = "signal")]
299 pub use self::Signal::*;
300 
301 #[cfg(target_os = "redox")]
302 #[cfg(feature = "signal")]
303 const 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")]
311 const 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")]
328 const 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")]
345 const 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")]
353 const 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")]
368 const 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 
375 feature! {
376 #![feature = "signal"]
377 
378 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
379 /// Iterate through all signals defined by this operating system
380 pub struct SignalIterator {
381     next: usize,
382 }
383 
384 impl 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 
398 impl Signal {
399     /// Iterate through all signals defined by this OS
400     pub const fn iterator() -> SignalIterator {
401         SignalIterator{next: 0}
402     }
403 }
404 
405 /// Alias for [`SIGABRT`]
406 pub const SIGIOT : Signal = SIGABRT;
407 /// Alias for [`SIGIO`]
408 #[cfg(not(target_os = "haiku"))]
409 pub const SIGPOLL : Signal = SIGIO;
410 /// Alias for [`SIGSYS`]
411 pub const SIGUNUSED : Signal = SIGSYS;
412 
413 cfg_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")]
425 libc_bitflags! {
426     /// Controls the behavior of a [`SigAction`]
427     #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
428     pub struct SaFlags: SaFlags_t {
429         /// When catching a [`Signal::SIGCHLD`] signal, the signal will be
430         /// generated only when a child process exits, not when a child process
431         /// stops.
432         SA_NOCLDSTOP;
433         /// When catching a [`Signal::SIGCHLD`] signal, the system will not
434         /// create zombie processes when children of the calling process exit.
435         #[cfg(not(target_os = "hurd"))]
436         SA_NOCLDWAIT;
437         /// Further occurrences of the delivered signal are not masked during
438         /// the execution of the handler.
439         SA_NODEFER;
440         /// The system will deliver the signal to the process on a signal stack,
441         /// specified by each thread with sigaltstack(2).
442         SA_ONSTACK;
443         /// The handler is reset back to the default at the moment the signal is
444         /// delivered.
445         SA_RESETHAND;
446         /// Requests that certain system calls restart if interrupted by this
447         /// signal.  See the man page for complete details.
448         SA_RESTART;
449         /// This flag is controlled internally by Nix.
450         SA_SIGINFO;
451     }
452 }
453 
454 #[cfg(feature = "signal")]
455 libc_enum! {
456     /// Specifies how certain functions should manipulate a signal mask
457     #[repr(i32)]
458     #[non_exhaustive]
459     #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
460     pub enum SigmaskHow {
461         /// The new mask is the union of the current mask and the specified set.
462         SIG_BLOCK,
463         /// The new mask is the intersection of the current mask and the
464         /// complement of the specified set.
465         SIG_UNBLOCK,
466         /// The current mask is replaced by the specified set.
467         SIG_SETMASK,
468     }
469 }
470 
471 feature! {
472 #![feature = "signal"]
473 
474 use crate::unistd::Pid;
475 use std::iter::Extend;
476 use std::iter::FromIterator;
477 use std::iter::IntoIterator;
478 
479 /// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
480 // We are using `transparent` here to be super sure that `SigSet`
481 // is represented exactly like the `sigset_t` struct from C.
482 #[repr(transparent)]
483 #[derive(Clone, Copy, Debug, Eq)]
484 pub struct SigSet {
485     sigset: libc::sigset_t
486 }
487 
488 impl SigSet {
489     /// Initialize to include all signals.
490     #[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     /// Initialize to include nothing.
499     #[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     /// Add the specified signal to the set.
508     #[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     /// Remove all signals from this set.
514     #[doc(alias("sigemptyset"))]
515     pub fn clear(&mut self) {
516         unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
517     }
518 
519     /// Remove the specified signal from this set.
520     #[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     /// Return whether this set includes the specified signal.
526     #[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     /// Returns an iterator that yields the signals contained in this set.
538     pub fn iter(&self) -> SigSetIter<'_> {
539         self.into_iter()
540     }
541 
542     /// Gets the currently blocked (masked) set of signals for the calling thread.
543     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     /// Sets the set of signals as the signal mask for the calling thread.
550     pub fn thread_set_mask(&self) -> Result<()> {
551         pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
552     }
553 
554     /// Adds the set of signals to the signal mask for the calling thread.
555     pub fn thread_block(&self) -> Result<()> {
556         pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
557     }
558 
559     /// Removes the set of signals from the signal mask for the calling thread.
560     pub fn thread_unblock(&self) -> Result<()> {
561         pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
562     }
563 
564     /// Sets the set of signals as the signal mask, and returns the old mask.
565     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     /// Suspends execution of the calling thread until one of the signals in the
572     /// signal mask becomes pending, and returns the accepted signal.
573     #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
574     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     /// Wait for a signal
586     ///
587     /// # Return value
588     /// If `sigsuspend(2)` is interrupted (EINTR), this function returns `Ok`.
589     /// If `sigsuspend(2)` set other error, this function returns `Err`.
590     ///
591     /// For more information see the
592     /// [`sigsuspend(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html).
593     #[cfg(any(
594         bsd,
595         linux_android,
596         solarish,
597         target_os = "haiku",
598         target_os = "hurd",
599         target_os = "aix",
600         target_os = "fushsia"
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     /// Converts a `libc::sigset_t` object to a [`SigSet`] without checking  whether the
615     /// `libc::sigset_t` is already initialized.
616     ///
617     /// # Safety
618     ///
619     /// The `sigset` passed in must be a valid an initialized `libc::sigset_t` by calling either
620     /// [`sigemptyset(3)`](https://man7.org/linux/man-pages/man3/sigemptyset.3p.html) or
621     /// [`sigfillset(3)`](https://man7.org/linux/man-pages/man3/sigfillset.3p.html).
622     /// Otherwise, the results are undefined.
623     pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet {
624         SigSet { sigset }
625     }
626 }
627 
628 impl 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 
636 impl 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 
647 impl 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 
656 impl 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 
664 impl AsRef<libc::sigset_t> for SigSet {
665     fn as_ref(&self) -> &libc::sigset_t {
666         &self.sigset
667     }
668 }
669 
670 // TODO: Consider specialization for the case where T is &SigSet and libc::sigorset is available.
671 impl 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 
680 impl 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 
689 impl 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 
700 impl 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 /// Iterator for a [`SigSet`].
711 ///
712 /// Call [`SigSet::iter`] to create an iterator.
713 #[derive(Clone, Debug)]
714 pub struct SigSetIter<'a> {
715     sigset: &'a SigSet,
716     inner: SignalIterator,
717 }
718 
719 impl 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 
732 impl<'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 /// A signal handler.
741 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
742 pub enum SigHandler {
743     /// Default signal handling.
744     SigDfl,
745     /// Request that the signal be ignored.
746     SigIgn,
747     /// Use the given signal-catching function, which takes in the signal.
748     Handler(extern fn(libc::c_int)),
749     /// Use the given signal-catching function, which takes in the signal, information about how
750     /// the signal was generated, and a pointer to the threads `ucontext_t`.
751     #[cfg(not(target_os = "redox"))]
752     SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
753 }
754 
755 /// Action to take on receipt of a signal. Corresponds to `sigaction`.
756 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
757 pub struct SigAction {
758     sigaction: libc::sigaction
759 }
760 
761 impl SigAction {
762     /// Creates a new action.
763     ///
764     /// The `SA_SIGINFO` bit in the `flags` argument is ignored (it will be set only if `handler`
765     /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
766     /// the signal-catching function.
767     pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
768         #[cfg(not(target_os = "aix"))]
769         unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
770             unsafe {
771                  (*p).sa_sigaction = match handler {
772                     SigHandler::SigDfl => libc::SIG_DFL,
773                     SigHandler::SigIgn => libc::SIG_IGN,
774                     SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
775                     #[cfg(not(target_os = "redox"))]
776                     SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
777                 };
778             }
779         }
780 
781         #[cfg(target_os = "aix")]
782         unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
783             unsafe {
784                 (*p).sa_union.__su_sigaction = match handler {
785                     SigHandler::SigDfl => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_DFL) },
786                     SigHandler::SigIgn => unsafe { mem::transmute::<usize, extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void)>(libc::SIG_IGN) },
787                     SigHandler::Handler(f) => unsafe { mem::transmute::<extern "C" fn(i32), extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void)>(f) },
788                     SigHandler::SigAction(f) => f,
789                 };
790             }
791         }
792 
793         let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
794         unsafe {
795             let p = s.as_mut_ptr();
796             install_sig(p, handler);
797             (*p).sa_flags = match handler {
798                 #[cfg(not(target_os = "redox"))]
799                 SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
800                 _ => (flags - SaFlags::SA_SIGINFO).bits(),
801             };
802             (*p).sa_mask = mask.sigset;
803 
804             SigAction { sigaction: s.assume_init() }
805         }
806     }
807 
808     /// Returns the flags set on the action.
809     pub fn flags(&self) -> SaFlags {
810         SaFlags::from_bits_truncate(self.sigaction.sa_flags)
811     }
812 
813     /// Returns the set of signals that are blocked during execution of the action's
814     /// signal-catching function.
815     pub fn mask(&self) -> SigSet {
816         SigSet { sigset: self.sigaction.sa_mask }
817     }
818 
819     /// Returns the action's handler.
820     #[cfg(not(target_os = "aix"))]
821     pub fn handler(&self) -> SigHandler {
822         match self.sigaction.sa_sigaction {
823             libc::SIG_DFL => SigHandler::SigDfl,
824             libc::SIG_IGN => SigHandler::SigIgn,
825             #[cfg(not(target_os = "redox"))]
826             p if self.flags().contains(SaFlags::SA_SIGINFO) =>
827                 SigHandler::SigAction(
828                 // Safe for one of two reasons:
829                 // * The SigHandler was created by SigHandler::new, in which
830                 //   case the pointer is correct, or
831                 // * The SigHandler was created by signal or sigaction, which
832                 //   are unsafe functions, so the caller should've somehow
833                 //   ensured that it is correctly initialized.
834                 unsafe{
835                     *(&p as *const usize
836                          as *const extern fn(_, _, _))
837                 }
838                 as extern fn(_, _, _)),
839             p => SigHandler::Handler(
840                 // Safe for one of two reasons:
841                 // * The SigHandler was created by SigHandler::new, in which
842                 //   case the pointer is correct, or
843                 // * The SigHandler was created by signal or sigaction, which
844                 //   are unsafe functions, so the caller should've somehow
845                 //   ensured that it is correctly initialized.
846                 unsafe{
847                     *(&p as *const usize
848                          as *const extern fn(libc::c_int))
849                 }
850                 as extern fn(libc::c_int)),
851         }
852     }
853 
854     /// Returns the action's handler.
855     #[cfg(target_os = "aix")]
856     pub fn handler(&self) -> SigHandler {
857         unsafe {
858         match self.sigaction.sa_union.__su_sigaction as usize {
859             libc::SIG_DFL => SigHandler::SigDfl,
860             libc::SIG_IGN => SigHandler::SigIgn,
861             p if self.flags().contains(SaFlags::SA_SIGINFO) =>
862                 SigHandler::SigAction(
863                     *(&p as *const usize
864                          as *const extern fn(_, _, _))
865                 as extern fn(_, _, _)),
866             p => SigHandler::Handler(
867                     *(&p as *const usize
868                          as *const extern fn(libc::c_int))
869                 as extern fn(libc::c_int)),
870         }
871         }
872     }
873 }
874 
875 /// Changes the action taken by a process on receipt of a specific signal.
876 ///
877 /// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous
878 /// action for the given signal. If `sigaction` fails, no new signal handler is installed.
879 ///
880 /// # Safety
881 ///
882 /// * Signal handlers may be called at any point during execution, which limits
883 ///   what is safe to do in the body of the signal-catching function. Be certain
884 ///   to only make syscalls that are explicitly marked safe for signal handlers
885 ///   and only share global data using atomics.
886 ///
887 /// * There is also no guarantee that the old signal handler was installed
888 ///   correctly.  If it was installed by this crate, it will be.  But if it was
889 ///   installed by, for example, C code, then there is no guarantee its function
890 ///   pointer is valid.  In that case, this function effectively dereferences a
891 ///   raw pointer of unknown provenance.
892 pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
893     let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
894 
895     let res = unsafe { libc::sigaction(signal as libc::c_int,
896                               &sigaction.sigaction as *const libc::sigaction,
897                               oldact.as_mut_ptr()) };
898 
899     Errno::result(res).map(|_| SigAction { sigaction: unsafe { oldact.assume_init() } })
900 }
901 
902 /// Signal management (see [signal(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
903 ///
904 /// Installs `handler` for the given `signal`, returning the previous signal
905 /// handler. `signal` should only be used following another call to `signal` or
906 /// if the current handler is the default. The return value of `signal` is
907 /// undefined after setting the handler with [`sigaction`][SigActionFn].
908 ///
909 /// # Safety
910 ///
911 /// If the pointer to the previous signal handler is invalid, undefined
912 /// behavior could be invoked when casting it back to a [`SigAction`][SigActionStruct].
913 ///
914 /// # Examples
915 ///
916 /// Ignore `SIGINT`:
917 ///
918 /// ```no_run
919 /// # use nix::sys::signal::{self, Signal, SigHandler};
920 /// unsafe { signal::signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
921 /// ```
922 ///
923 /// Use a signal handler to set a flag variable:
924 ///
925 /// ```no_run
926 /// # use std::convert::TryFrom;
927 /// # use std::sync::atomic::{AtomicBool, Ordering};
928 /// # use nix::sys::signal::{self, Signal, SigHandler};
929 /// static SIGNALED: AtomicBool = AtomicBool::new(false);
930 ///
931 /// extern fn handle_sigint(signal: libc::c_int) {
932 ///     let signal = Signal::try_from(signal).unwrap();
933 ///     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
934 /// }
935 ///
936 /// fn main() {
937 ///     let handler = SigHandler::Handler(handle_sigint);
938 ///     unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap();
939 /// }
940 /// ```
941 ///
942 /// # Errors
943 ///
944 /// Returns [`Error(Errno::EOPNOTSUPP)`] if `handler` is
945 /// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead.
946 ///
947 /// `signal` also returns any error from `libc::signal`, such as when an attempt
948 /// is made to catch a signal that cannot be caught or to ignore a signal that
949 /// cannot be ignored.
950 ///
951 /// [`Error::UnsupportedOperation`]: ../../enum.Error.html#variant.UnsupportedOperation
952 /// [SigActionStruct]: struct.SigAction.html
953 /// [sigactionFn]: fn.sigaction.html
954 pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
955     let signal = signal as libc::c_int;
956     let res = match handler {
957         SigHandler::SigDfl => unsafe { libc::signal(signal, libc::SIG_DFL) },
958         SigHandler::SigIgn => unsafe { libc::signal(signal, libc::SIG_IGN) },
959         SigHandler::Handler(handler) => unsafe { libc::signal(signal, handler as libc::sighandler_t) },
960         #[cfg(not(target_os = "redox"))]
961         SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
962     };
963     Errno::result(res).map(|oldhandler| {
964         match oldhandler {
965             libc::SIG_DFL => SigHandler::SigDfl,
966             libc::SIG_IGN => SigHandler::SigIgn,
967             p => SigHandler::Handler(
968                 unsafe { *(&p as *const usize as *const extern fn(libc::c_int)) } as extern fn(libc::c_int)),
969         }
970     })
971 }
972 
973 fn do_pthread_sigmask(how: SigmaskHow,
974                        set: Option<&SigSet>,
975                        oldset: Option<*mut libc::sigset_t>) -> Result<()> {
976     if set.is_none() && oldset.is_none() {
977         return Ok(())
978     }
979 
980     let res = unsafe {
981         // if set or oldset is None, pass in null pointers instead
982         libc::pthread_sigmask(how as libc::c_int,
983                              set.map_or_else(ptr::null::<libc::sigset_t>,
984                                              |s| &s.sigset as *const libc::sigset_t),
985                              oldset.unwrap_or(ptr::null_mut())
986                              )
987     };
988 
989     Errno::result(res).map(drop)
990 }
991 
992 /// Manages the signal mask (set of blocked signals) for the calling thread.
993 ///
994 /// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
995 /// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
996 /// and no modification will take place.
997 ///
998 /// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
999 ///
1000 /// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
1001 /// and then it will be updated with `set`.
1002 ///
1003 /// If both `set` and `oldset` is None, this function is a no-op.
1004 ///
1005 /// For more information, visit the [`pthread_sigmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html),
1006 /// or [`sigprocmask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
1007 pub fn pthread_sigmask(how: SigmaskHow,
1008                        set: Option<&SigSet>,
1009                        oldset: Option<&mut SigSet>) -> Result<()>
1010 {
1011     do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
1012 }
1013 
1014 /// Examine and change blocked signals.
1015 ///
1016 /// For more information see the [`sigprocmask` man
1017 /// pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
1018 pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
1019     if set.is_none() && oldset.is_none() {
1020         return Ok(())
1021     }
1022 
1023     let res = unsafe {
1024         // if set or oldset is None, pass in null pointers instead
1025         libc::sigprocmask(how as libc::c_int,
1026                           set.map_or_else(ptr::null::<libc::sigset_t>,
1027                                           |s| &s.sigset as *const libc::sigset_t),
1028                           oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
1029                                              |os| &mut os.sigset as *mut libc::sigset_t))
1030     };
1031 
1032     Errno::result(res).map(drop)
1033 }
1034 
1035 /// Send a signal to a process
1036 ///
1037 /// # Arguments
1038 ///
1039 /// * `pid` -    Specifies which processes should receive the signal.
1040 ///   - If positive, specifies an individual process.
1041 ///   - If zero, the signal will be sent to all processes whose group
1042 ///     ID is equal to the process group ID of the sender.  This is a
1043 #[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
1044 #[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
1045 ///   - If `-1` and the process has super-user privileges, the signal
1046 ///     is sent to all processes exclusing system processes.
1047 ///   - If less than `-1`, the signal is sent to all processes whose
1048 ///     process group ID is equal to the absolute value of `pid`.
1049 /// * `signal` - Signal to send. If `None`, error checking is performed
1050 ///              but no signal is actually sent.
1051 ///
1052 /// See Also
1053 /// [`kill(2)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html)
1054 pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
1055     let res = unsafe { libc::kill(pid.into(),
1056                                   match signal.into() {
1057                                       Some(s) => s as libc::c_int,
1058                                       None => 0,
1059                                   }) };
1060 
1061     Errno::result(res).map(drop)
1062 }
1063 
1064 /// Send a signal to a process group
1065 ///
1066 /// # Arguments
1067 ///
1068 /// * `pgrp` -   Process group to signal.  If less then or equal 1, the behavior
1069 ///              is platform-specific.
1070 /// * `signal` - Signal to send. If `None`, `killpg` will only preform error
1071 ///              checking and won't send any signal.
1072 ///
1073 /// See Also [killpg(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
1074 #[cfg(not(target_os = "fuchsia"))]
1075 pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
1076     let res = unsafe { libc::killpg(pgrp.into(),
1077                                   match signal.into() {
1078                                       Some(s) => s as libc::c_int,
1079                                       None => 0,
1080                                   }) };
1081 
1082     Errno::result(res).map(drop)
1083 }
1084 
1085 /// Send a signal to the current thread
1086 ///
1087 /// See Also [raise(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/raise.html)
1088 pub fn raise(signal: Signal) -> Result<()> {
1089     let res = unsafe { libc::raise(signal as libc::c_int) };
1090 
1091     Errno::result(res).map(drop)
1092 }
1093 }
1094 
1095 feature! {
1096 #![any(feature = "aio", feature = "signal")]
1097 
1098 /// Identifies a thread for [`SigevNotify::SigevThreadId`]
1099 #[cfg(target_os = "freebsd")]
1100 pub type type_of_thread_id = libc::lwpid_t;
1101 /// Identifies a thread for [`SigevNotify::SigevThreadId`]
1102 #[cfg(all(not(target_os = "hurd"), any(target_env = "gnu", target_env = "uclibc")))]
1103 pub type type_of_thread_id = libc::pid_t;
1104 
1105 /// Specifies the notification method used by a [`SigEvent`]
1106 // sigval is actually a union of a int and a void*.  But it's never really used
1107 // as a pointer, because neither libc nor the kernel ever dereference it.  nix
1108 // therefore presents it as an intptr_t, which is how kevent uses it.
1109 #[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))]
1110 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1111 pub enum SigevNotify {
1112     /// No notification will be delivered
1113     SigevNone,
1114     /// Notify by delivering a signal to the process.
1115     SigevSignal {
1116         /// Signal to deliver
1117         signal: Signal,
1118         /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
1119         /// structure of the queued signal.
1120         si_value: libc::intptr_t
1121     },
1122     // Note: SIGEV_THREAD is not implemented, but could be if desired.
1123     /// Notify by delivering an event to a kqueue.
1124     #[cfg(freebsdlike)]
1125     SigevKevent {
1126         /// File descriptor of the kqueue to notify.
1127         kq: RawFd,
1128         /// Will be contained in the kevent's `udata` field.
1129         udata: libc::intptr_t
1130     },
1131     /// Notify by delivering an event to a kqueue, with optional event flags set
1132     #[cfg(target_os = "freebsd")]
1133     #[cfg(feature = "event")]
1134     SigevKeventFlags {
1135         /// File descriptor of the kqueue to notify.
1136         kq: RawFd,
1137         /// Will be contained in the kevent's `udata` field.
1138         udata: libc::intptr_t,
1139         /// Flags that will be set on the delivered event.  See `kevent(2)`.
1140         flags: crate::sys::event::EventFlag
1141     },
1142     /// Notify by delivering a signal to a thread.
1143     #[cfg(any(
1144             target_os = "freebsd",
1145             target_env = "gnu",
1146             target_env = "uclibc",
1147     ))]
1148     SigevThreadId {
1149         /// Signal to send
1150         signal: Signal,
1151         /// LWP ID of the thread to notify
1152         thread_id: type_of_thread_id,
1153         /// Will be present in the `si_value` field of the [`libc::siginfo_t`]
1154         /// structure of the queued signal.
1155         si_value: libc::intptr_t
1156     },
1157 }
1158 }
1159 
1160 #[cfg(not(any(
1161     target_os = "fuchsia",
1162     target_os = "hurd",
1163     target_os = "openbsd",
1164     target_os = "redox"
1165 )))]
1166 mod sigevent {
1167     feature! {
1168     #![any(feature = "aio", feature = "signal")]
1169 
1170     use std::mem;
1171     use super::SigevNotify;
1172 
1173     #[cfg(target_os = "freebsd")]
1174     pub(crate) use ffi::sigevent as libc_sigevent;
1175     #[cfg(not(target_os = "freebsd"))]
1176     pub(crate) use libc::sigevent as libc_sigevent;
1177 
1178     // For FreeBSD only, we define the C structure here.  Because the structure
1179     // defined in libc isn't correct.  The real sigevent contains union fields,
1180     // but libc could not represent those when sigevent was originally added, so
1181     // instead libc simply defined the most useful field.  Now that Rust can
1182     // represent unions, there's a PR to libc to fix it.  However, it's stuck
1183     // forever due to backwards compatibility concerns.  Even though there's a
1184     // workaround, libc refuses to merge it.  I think it's just too complicated
1185     // for them to want to think about right now, because that project is
1186     // short-staffed.  So we define it here instead, so we won't have to wait on
1187     // libc.
1188     // https://github.com/rust-lang/libc/pull/2813
1189     #[cfg(target_os = "freebsd")]
1190     mod ffi {
1191         use std::{fmt, hash};
1192 
1193         #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1194         #[repr(C)]
1195         pub struct __c_anonymous_sigev_thread {
1196             pub _function: *mut libc::c_void,   // Actually a function pointer
1197             pub _attribute: *mut libc::pthread_attr_t,
1198         }
1199         #[derive(Clone, Copy)]
1200         // This will never be used on its own, and its parent has a Debug impl,
1201         // so it doesn't need one.
1202         #[allow(missing_debug_implementations)]
1203         #[repr(C)]
1204         pub union __c_anonymous_sigev_un {
1205             pub _threadid: libc::__lwpid_t,
1206             pub _sigev_thread: __c_anonymous_sigev_thread,
1207             pub _kevent_flags: libc::c_ushort,
1208             __spare__: [libc::c_long; 8],
1209         }
1210 
1211         #[derive(Clone, Copy)]
1212         #[repr(C)]
1213         pub struct sigevent {
1214             pub sigev_notify: libc::c_int,
1215             pub sigev_signo: libc::c_int,
1216             pub sigev_value: libc::sigval,
1217             pub _sigev_un: __c_anonymous_sigev_un,
1218         }
1219 
1220         impl fmt::Debug for sigevent {
1221             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1222                 let mut ds = f.debug_struct("sigevent");
1223                 ds.field("sigev_notify", &self.sigev_notify)
1224                     .field("sigev_signo", &self.sigev_signo)
1225                     .field("sigev_value", &self.sigev_value);
1226                 // Safe because we check the sigev_notify discriminant
1227                 unsafe {
1228                     match self.sigev_notify {
1229                         libc::SIGEV_KEVENT => {
1230                             ds.field("sigev_notify_kevent_flags", &self._sigev_un._kevent_flags);
1231                         }
1232                         libc::SIGEV_THREAD_ID => {
1233                             ds.field("sigev_notify_thread_id", &self._sigev_un._threadid);
1234                         }
1235                         libc::SIGEV_THREAD => {
1236                             ds.field("sigev_notify_function", &self._sigev_un._sigev_thread._function);
1237                             ds.field("sigev_notify_attributes", &self._sigev_un._sigev_thread._attribute);
1238                         }
1239                         _ => ()
1240                     };
1241                 }
1242                 ds.finish()
1243             }
1244         }
1245 
1246         impl PartialEq for sigevent {
1247             fn eq(&self, other: &Self) -> bool {
1248                 let mut equals = self.sigev_notify == other.sigev_notify;
1249                 equals &= self.sigev_signo == other.sigev_signo;
1250                 equals &= self.sigev_value == other.sigev_value;
1251                 // Safe because we check the sigev_notify discriminant
1252                 unsafe {
1253                     match self.sigev_notify {
1254                         libc::SIGEV_KEVENT => {
1255                             equals &= self._sigev_un._kevent_flags == other._sigev_un._kevent_flags;
1256                         }
1257                         libc::SIGEV_THREAD_ID => {
1258                             equals &= self._sigev_un._threadid == other._sigev_un._threadid;
1259                         }
1260                         libc::SIGEV_THREAD => {
1261                             equals &= self._sigev_un._sigev_thread == other._sigev_un._sigev_thread;
1262                         }
1263                         _ => /* The union field is don't care */ ()
1264                     }
1265                 }
1266                 equals
1267             }
1268         }
1269 
1270         impl Eq for sigevent {}
1271 
1272         impl hash::Hash for sigevent {
1273             fn hash<H: hash::Hasher>(&self, s: &mut H) {
1274                 self.sigev_notify.hash(s);
1275                 self.sigev_signo.hash(s);
1276                 self.sigev_value.hash(s);
1277                 // Safe because we check the sigev_notify discriminant
1278                 unsafe {
1279                     match self.sigev_notify {
1280                         libc::SIGEV_KEVENT => {
1281                             self._sigev_un._kevent_flags.hash(s);
1282                         }
1283                         libc::SIGEV_THREAD_ID => {
1284                             self._sigev_un._threadid.hash(s);
1285                         }
1286                         libc::SIGEV_THREAD => {
1287                             self._sigev_un._sigev_thread.hash(s);
1288                         }
1289                         _ => /* The union field is don't care */ ()
1290                     }
1291                 }
1292             }
1293         }
1294     }
1295 
1296     /// Used to request asynchronous notification of the completion of certain
1297     /// events, such as POSIX AIO and timers.
1298     #[repr(C)]
1299     #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1300     // It can't be Copy on all platforms.
1301     #[allow(missing_copy_implementations)]
1302     pub struct SigEvent {
1303         sigevent: libc_sigevent
1304     }
1305 
1306     impl SigEvent {
1307         /// **Note:** this constructor does not allow the user to set the
1308         /// `sigev_notify_kevent_flags` field.  That's considered ok because on FreeBSD
1309         /// at least those flags don't do anything useful.  That field is part of a
1310         /// union that shares space with the more genuinely useful fields.
1311         ///
1312         /// **Note:** This constructor also doesn't allow the caller to set the
1313         /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
1314         /// required for `SIGEV_THREAD`.  That's considered ok because on no operating
1315         /// system is `SIGEV_THREAD` the most efficient way to deliver AIO
1316         /// notification.  FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
1317         /// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
1318         /// `SIGEV_SIGNAL`.  That field is part of a union that shares space with the
1319         /// more genuinely useful `sigev_notify_thread_id`
1320         pub fn new(sigev_notify: SigevNotify) -> SigEvent {
1321             let mut sev: libc_sigevent = unsafe { mem::zeroed() };
1322             match sigev_notify {
1323                 SigevNotify::SigevNone => {
1324                     sev.sigev_notify = libc::SIGEV_NONE;
1325                 },
1326                 SigevNotify::SigevSignal{signal, si_value} => {
1327                     sev.sigev_notify = libc::SIGEV_SIGNAL;
1328                     sev.sigev_signo = signal as libc::c_int;
1329                     sev.sigev_value.sival_ptr = si_value as *mut libc::c_void
1330                 },
1331                 #[cfg(freebsdlike)]
1332                 SigevNotify::SigevKevent{kq, udata} => {
1333                     sev.sigev_notify = libc::SIGEV_KEVENT;
1334                     sev.sigev_signo = kq;
1335                     sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
1336                 },
1337                 #[cfg(target_os = "freebsd")]
1338                 #[cfg(feature = "event")]
1339                 SigevNotify::SigevKeventFlags{kq, udata, flags} => {
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                     sev._sigev_un._kevent_flags = flags.bits();
1344                 },
1345                 #[cfg(target_os = "freebsd")]
1346                 SigevNotify::SigevThreadId{signal, thread_id, si_value} => {
1347                     sev.sigev_notify = libc::SIGEV_THREAD_ID;
1348                     sev.sigev_signo = signal as libc::c_int;
1349                     sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
1350                     sev._sigev_un._threadid = thread_id;
1351                 }
1352                 #[cfg(any(target_env = "gnu", target_env = "uclibc"))]
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_notify_thread_id = thread_id;
1358                 }
1359             }
1360             SigEvent{sigevent: sev}
1361         }
1362 
1363         /// Return a copy of the inner structure
1364         #[cfg(target_os = "freebsd")]
1365         pub fn sigevent(&self) -> libc::sigevent {
1366             // Safe because they're really the same structure.  See
1367             // https://github.com/rust-lang/libc/pull/2813
1368             unsafe {
1369                 mem::transmute::<libc_sigevent, libc::sigevent>(self.sigevent)
1370             }
1371         }
1372 
1373         /// Return a copy of the inner structure
1374         #[cfg(not(target_os = "freebsd"))]
1375         pub fn sigevent(&self) -> libc::sigevent {
1376             self.sigevent
1377         }
1378 
1379         /// Returns a mutable pointer to the `sigevent` wrapped by `self`
1380         #[cfg(target_os = "freebsd")]
1381         pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1382             // Safe because they're really the same structure.  See
1383             // https://github.com/rust-lang/libc/pull/2813
1384             &mut self.sigevent as *mut libc_sigevent as *mut libc::sigevent
1385         }
1386 
1387         /// Returns a mutable pointer to the `sigevent` wrapped by `self`
1388         #[cfg(not(target_os = "freebsd"))]
1389         pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1390             &mut self.sigevent
1391         }
1392     }
1393 
1394     impl<'a> From<&'a libc::sigevent> for SigEvent {
1395         #[cfg(target_os = "freebsd")]
1396         fn from(sigevent: &libc::sigevent) -> Self {
1397             // Safe because they're really the same structure.  See
1398             // https://github.com/rust-lang/libc/pull/2813
1399             let sigevent = unsafe {
1400                 mem::transmute::<libc::sigevent, libc_sigevent>(*sigevent)
1401             };
1402             SigEvent{ sigevent }
1403         }
1404         #[cfg(not(target_os = "freebsd"))]
1405         fn from(sigevent: &libc::sigevent) -> Self {
1406             SigEvent{ sigevent: *sigevent }
1407         }
1408     }
1409     }
1410 }
1411