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}