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 = "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 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#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
757pub struct SigAction {
758 sigaction: libc::sigaction
759}
760
761impl SigAction {
762 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 pub fn flags(&self) -> SaFlags {
810 SaFlags::from_bits_truncate(self.sigaction.sa_flags)
811 }
812
813 pub fn mask(&self) -> SigSet {
816 SigSet { sigset: self.sigaction.sa_mask }
817 }
818
819 #[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 unsafe{
835 *(&p as *const usize
836 as *const extern fn(_, _, _))
837 }
838 as extern fn(_, _, _)),
839 p => SigHandler::Handler(
840 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 #[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
875pub 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
902pub 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
973fn 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 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
992pub 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
1014pub 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 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#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
1044#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
1045pub 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#[cfg(not(target_os = "fuchsia"))]
1075pub 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
1085pub 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
1095feature! {
1096#![any(feature = "aio", feature = "signal")]
1097
1098#[cfg(target_os = "freebsd")]
1100pub type type_of_thread_id = libc::lwpid_t;
1101#[cfg(all(not(target_os = "hurd"), any(target_env = "gnu", target_env = "uclibc")))]
1103pub type type_of_thread_id = libc::pid_t;
1104
1105#[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))]
1110#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1111pub enum SigevNotify {
1112 SigevNone,
1114 SigevSignal {
1116 signal: Signal,
1118 si_value: libc::intptr_t
1121 },
1122 #[cfg(freebsdlike)]
1125 SigevKevent {
1126 kq: RawFd,
1128 udata: libc::intptr_t
1130 },
1131 #[cfg(target_os = "freebsd")]
1133 #[cfg(feature = "event")]
1134 SigevKeventFlags {
1135 kq: RawFd,
1137 udata: libc::intptr_t,
1139 flags: crate::sys::event::EventFlag
1141 },
1142 #[cfg(any(
1144 target_os = "freebsd",
1145 target_env = "gnu",
1146 target_env = "uclibc",
1147 ))]
1148 SigevThreadId {
1149 signal: Signal,
1151 thread_id: type_of_thread_id,
1153 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)))]
1166mod 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 #[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, pub _attribute: *mut libc::pthread_attr_t,
1198 }
1199 #[derive(Clone, Copy)]
1200 #[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 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 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 _ => ()
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 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 _ => ()
1290 }
1291 }
1292 }
1293 }
1294 }
1295
1296 #[repr(C)]
1299 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1300 #[allow(missing_copy_implementations)]
1302 pub struct SigEvent {
1303 sigevent: libc_sigevent
1304 }
1305
1306 impl SigEvent {
1307 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 #[cfg(target_os = "freebsd")]
1365 pub fn sigevent(&self) -> libc::sigevent {
1366 unsafe {
1369 mem::transmute::<libc_sigevent, libc::sigevent>(self.sigevent)
1370 }
1371 }
1372
1373 #[cfg(not(target_os = "freebsd"))]
1375 pub fn sigevent(&self) -> libc::sigevent {
1376 self.sigevent
1377 }
1378
1379 #[cfg(target_os = "freebsd")]
1381 pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1382 &mut self.sigevent as *mut libc_sigevent as *mut libc::sigevent
1385 }
1386
1387 #[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 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}