1use crate::errno::Errno;
4use crate::{Error, Result};
5use cfg_if::cfg_if;
6use std::fmt;
7use std::hash::{Hash, Hasher};
8use std::mem;
9use std::ops::BitOr;
10use std::ptr;
11use std::str::FromStr;
12
13#[cfg(not(any(
14 target_os = "fuchsia",
15 target_os = "hurd",
16 target_os = "openbsd",
17 target_os = "redox"
18)))]
19#[cfg(any(feature = "aio", feature = "signal"))]
20pub use self::sigevent::*;
21
22#[cfg(any(feature = "aio", feature = "process", feature = "signal"))]
23libc_enum! {
24 #[repr(i32)]
30 #[non_exhaustive]
31 #[cfg_attr(docsrs, doc(cfg(any(feature = "aio", feature = "signal"))))]
32 pub enum Signal {
33 SIGHUP,
35 SIGINT,
37 SIGQUIT,
39 SIGILL,
41 SIGTRAP,
43 SIGABRT,
45 SIGBUS,
47 SIGFPE,
49 SIGKILL,
51 SIGUSR1,
53 SIGSEGV,
55 SIGUSR2,
57 SIGPIPE,
59 SIGALRM,
61 SIGTERM,
63 #[cfg(all(any(linux_android, target_os = "emscripten",
65 target_os = "fuchsia"),
66 not(any(target_arch = "mips",
67 target_arch = "mips32r6",
68 target_arch = "mips64",
69 target_arch = "mips64r6",
70 target_arch = "sparc",
71 target_arch = "sparc64"))))]
72 SIGSTKFLT,
73 SIGCHLD,
75 SIGCONT,
77 SIGSTOP,
79 SIGTSTP,
81 SIGTTIN,
83 SIGTTOU,
85 SIGURG,
87 SIGXCPU,
89 SIGXFSZ,
91 SIGVTALRM,
93 SIGPROF,
95 SIGWINCH,
97 #[cfg(not(target_os = "haiku"))]
99 SIGIO,
100 #[cfg(any(linux_android, target_os = "emscripten",
101 target_os = "fuchsia", target_os = "aix"))]
102 SIGPWR,
104 SIGSYS,
106 #[cfg(not(any(linux_android, target_os = "emscripten",
107 target_os = "fuchsia",
108 target_os = "redox", target_os = "haiku")))]
109 SIGEMT,
111 #[cfg(not(any(linux_android, target_os = "emscripten",
112 target_os = "fuchsia", target_os = "redox",
113 target_os = "haiku", target_os = "aix",
114 target_os = "solaris", target_os = "cygwin")))]
115 SIGINFO,
117 }
118 impl TryFrom<i32>
119}
120
121#[cfg(feature = "signal")]
122impl FromStr for Signal {
123 type Err = Error;
124 fn from_str(s: &str) -> Result<Signal> {
125 Ok(match s {
126 "SIGHUP" => Signal::SIGHUP,
127 "SIGINT" => Signal::SIGINT,
128 "SIGQUIT" => Signal::SIGQUIT,
129 "SIGILL" => Signal::SIGILL,
130 "SIGTRAP" => Signal::SIGTRAP,
131 "SIGABRT" => Signal::SIGABRT,
132 "SIGBUS" => Signal::SIGBUS,
133 "SIGFPE" => Signal::SIGFPE,
134 "SIGKILL" => Signal::SIGKILL,
135 "SIGUSR1" => Signal::SIGUSR1,
136 "SIGSEGV" => Signal::SIGSEGV,
137 "SIGUSR2" => Signal::SIGUSR2,
138 "SIGPIPE" => Signal::SIGPIPE,
139 "SIGALRM" => Signal::SIGALRM,
140 "SIGTERM" => Signal::SIGTERM,
141 #[cfg(all(
142 any(
143 linux_android,
144 target_os = "emscripten",
145 target_os = "fuchsia",
146 ),
147 not(any(
148 target_arch = "mips",
149 target_arch = "mips32r6",
150 target_arch = "mips64",
151 target_arch = "mips64r6",
152 target_arch = "sparc",
153 target_arch = "sparc64"
154 ))
155 ))]
156 "SIGSTKFLT" => Signal::SIGSTKFLT,
157 "SIGCHLD" => Signal::SIGCHLD,
158 "SIGCONT" => Signal::SIGCONT,
159 "SIGSTOP" => Signal::SIGSTOP,
160 "SIGTSTP" => Signal::SIGTSTP,
161 "SIGTTIN" => Signal::SIGTTIN,
162 "SIGTTOU" => Signal::SIGTTOU,
163 "SIGURG" => Signal::SIGURG,
164 "SIGXCPU" => Signal::SIGXCPU,
165 "SIGXFSZ" => Signal::SIGXFSZ,
166 "SIGVTALRM" => Signal::SIGVTALRM,
167 "SIGPROF" => Signal::SIGPROF,
168 "SIGWINCH" => Signal::SIGWINCH,
169 #[cfg(not(target_os = "haiku"))]
170 "SIGIO" => Signal::SIGIO,
171 #[cfg(any(
172 linux_android,
173 target_os = "emscripten",
174 target_os = "fuchsia",
175 ))]
176 "SIGPWR" => Signal::SIGPWR,
177 "SIGSYS" => Signal::SIGSYS,
178 #[cfg(not(any(
179 linux_android,
180 target_os = "emscripten",
181 target_os = "fuchsia",
182 target_os = "redox",
183 target_os = "haiku"
184 )))]
185 "SIGEMT" => Signal::SIGEMT,
186 #[cfg(not(any(
187 linux_android,
188 target_os = "emscripten",
189 target_os = "fuchsia",
190 target_os = "redox",
191 target_os = "aix",
192 target_os = "haiku",
193 target_os = "solaris",
194 target_os = "cygwin"
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 = "sparc",
238 target_arch = "sparc64"
239 ))
240 ))]
241 Signal::SIGSTKFLT => "SIGSTKFLT",
242 Signal::SIGCHLD => "SIGCHLD",
243 Signal::SIGCONT => "SIGCONT",
244 Signal::SIGSTOP => "SIGSTOP",
245 Signal::SIGTSTP => "SIGTSTP",
246 Signal::SIGTTIN => "SIGTTIN",
247 Signal::SIGTTOU => "SIGTTOU",
248 Signal::SIGURG => "SIGURG",
249 Signal::SIGXCPU => "SIGXCPU",
250 Signal::SIGXFSZ => "SIGXFSZ",
251 Signal::SIGVTALRM => "SIGVTALRM",
252 Signal::SIGPROF => "SIGPROF",
253 Signal::SIGWINCH => "SIGWINCH",
254 #[cfg(not(target_os = "haiku"))]
255 Signal::SIGIO => "SIGIO",
256 #[cfg(any(
257 linux_android,
258 target_os = "emscripten",
259 target_os = "fuchsia",
260 target_os = "aix",
261 ))]
262 Signal::SIGPWR => "SIGPWR",
263 Signal::SIGSYS => "SIGSYS",
264 #[cfg(not(any(
265 linux_android,
266 target_os = "emscripten",
267 target_os = "fuchsia",
268 target_os = "redox",
269 target_os = "haiku"
270 )))]
271 Signal::SIGEMT => "SIGEMT",
272 #[cfg(not(any(
273 linux_android,
274 target_os = "emscripten",
275 target_os = "fuchsia",
276 target_os = "redox",
277 target_os = "aix",
278 target_os = "haiku",
279 target_os = "solaris",
280 target_os = "cygwin"
281 )))]
282 Signal::SIGINFO => "SIGINFO",
283 }
284 }
285}
286
287#[cfg(feature = "signal")]
288impl AsRef<str> for Signal {
289 fn as_ref(&self) -> &str {
290 self.as_str()
291 }
292}
293
294#[cfg(feature = "signal")]
295impl fmt::Display for Signal {
296 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
297 f.write_str(self.as_ref())
298 }
299}
300
301#[cfg(feature = "signal")]
302pub use self::Signal::*;
303
304#[cfg(target_os = "redox")]
305#[cfg(feature = "signal")]
306const SIGNALS: [Signal; 29] = [
307 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
308 SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
309 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
310 SIGPROF, SIGWINCH, SIGIO, SIGSYS,
311];
312#[cfg(target_os = "haiku")]
313#[cfg(feature = "signal")]
314const SIGNALS: [Signal; 28] = [
315 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
316 SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
317 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
318 SIGPROF, SIGWINCH, SIGSYS,
319];
320#[cfg(all(
321 any(linux_android, target_os = "emscripten", target_os = "fuchsia"),
322 not(any(
323 target_arch = "mips",
324 target_arch = "mips32r6",
325 target_arch = "mips64",
326 target_arch = "mips64r6",
327 target_arch = "sparc",
328 target_arch = "sparc64"
329 ))
330))]
331#[cfg(feature = "signal")]
332const SIGNALS: [Signal; 31] = [
333 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
334 SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGSTKFLT, SIGCHLD,
335 SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ,
336 SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
337];
338#[cfg(all(
339 any(linux_android, target_os = "emscripten", target_os = "fuchsia"),
340 any(
341 target_arch = "mips",
342 target_arch = "mips32r6",
343 target_arch = "mips64",
344 target_arch = "mips64r6",
345 target_arch = "sparc",
346 target_arch = "sparc64"
347 )
348))]
349#[cfg(feature = "signal")]
350const SIGNALS: [Signal; 30] = [
351 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
352 SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
353 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
354 SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
355];
356#[cfg(target_os = "aix")]
357#[cfg(feature = "signal")]
358const SIGNALS: [Signal; 30] = [
359 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGEMT, SIGFPE, SIGKILL, SIGSEGV,
360 SIGSYS, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, SIGUSR2, SIGPWR, SIGWINCH,
361 SIGURG, SIGPOLL, SIGIO, SIGSTOP, SIGTSTP, SIGCONT, SIGTTIN, SIGTTOU,
362 SIGVTALRM, SIGPROF, SIGXCPU, SIGXFSZ, SIGTRAP,
363];
364#[cfg(any(target_os = "solaris", target_os = "cygwin"))]
365#[cfg(feature = "signal")]
366const SIGNALS: [Signal; 30] = [
367 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
368 SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
369 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
370 SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT,
371];
372#[cfg(not(any(
373 linux_android,
374 target_os = "fuchsia",
375 target_os = "emscripten",
376 target_os = "aix",
377 target_os = "redox",
378 target_os = "haiku",
379 target_os = "solaris",
380 target_os = "cygwin"
381)))]
382#[cfg(feature = "signal")]
383const SIGNALS: [Signal; 31] = [
384 SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
385 SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
386 SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
387 SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT, SIGINFO,
388];
389
390feature! {
391#![feature = "signal"]
392
393#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
394pub struct SignalIterator {
396 next: usize,
397}
398
399impl Iterator for SignalIterator {
400 type Item = Signal;
401
402 fn next(&mut self) -> Option<Signal> {
403 if self.next < SIGNALS.len() {
404 let next_signal = SIGNALS[self.next];
405 self.next += 1;
406 Some(next_signal)
407 } else {
408 None
409 }
410 }
411}
412
413impl Signal {
414 pub const fn iterator() -> SignalIterator {
416 SignalIterator{next: 0}
417 }
418}
419
420pub const SIGIOT : Signal = SIGABRT;
422#[cfg(not(target_os = "haiku"))]
424pub const SIGPOLL : Signal = SIGIO;
425pub const SIGUNUSED : Signal = SIGSYS;
427
428cfg_if! {
429 if #[cfg(target_os = "redox")] {
430 type SaFlags_t = libc::c_ulong;
431 } else if #[cfg(target_env = "uclibc")] {
432 type SaFlags_t = libc::c_ulong;
433 } else {
434 type SaFlags_t = libc::c_int;
435 }
436}
437}
438
439#[cfg(feature = "signal")]
440libc_bitflags! {
441 #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
443 pub struct SaFlags: SaFlags_t {
444 SA_NOCLDSTOP;
448 #[cfg(not(target_os = "hurd"))]
451 SA_NOCLDWAIT;
452 SA_NODEFER;
455 SA_ONSTACK;
458 SA_RESETHAND;
461 SA_RESTART;
464 SA_SIGINFO;
466 }
467}
468
469#[cfg(feature = "signal")]
470libc_enum! {
471 #[repr(i32)]
473 #[non_exhaustive]
474 #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
475 pub enum SigmaskHow {
476 SIG_BLOCK,
478 SIG_UNBLOCK,
481 SIG_SETMASK,
483 }
484}
485
486feature! {
487#![feature = "signal"]
488
489use crate::unistd::Pid;
490use std::iter::Extend;
491use std::iter::FromIterator;
492use std::iter::IntoIterator;
493
494#[repr(transparent)]
498#[derive(Clone, Copy, Debug, Eq)]
499pub struct SigSet {
500 sigset: libc::sigset_t
501}
502
503impl SigSet {
504 #[doc(alias("sigfillset"))]
506 pub fn all() -> SigSet {
507 let mut sigset = mem::MaybeUninit::uninit();
508 let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
509
510 unsafe{ SigSet { sigset: sigset.assume_init() } }
511 }
512
513 #[doc(alias("sigemptyset"))]
515 pub fn empty() -> SigSet {
516 let mut sigset = mem::MaybeUninit::uninit();
517 let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
518
519 unsafe{ SigSet { sigset: sigset.assume_init() } }
520 }
521
522 #[doc(alias("sigaddset"))]
524 pub fn add(&mut self, signal: Signal) {
525 unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
526 }
527
528 #[doc(alias("sigemptyset"))]
530 pub fn clear(&mut self) {
531 unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
532 }
533
534 #[doc(alias("sigdelset"))]
536 pub fn remove(&mut self, signal: Signal) {
537 unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
538 }
539
540 #[doc(alias("sigismember"))]
542 pub fn contains(&self, signal: Signal) -> bool {
543 let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
544
545 match res {
546 1 => true,
547 0 => false,
548 _ => unreachable!("unexpected value from sigismember"),
549 }
550 }
551
552 pub fn iter(&self) -> SigSetIter<'_> {
554 self.into_iter()
555 }
556
557 pub fn thread_get_mask() -> Result<SigSet> {
559 let mut oldmask = mem::MaybeUninit::uninit();
560 do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
561 Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
562 }
563
564 pub fn thread_set_mask(&self) -> Result<()> {
566 pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
567 }
568
569 pub fn thread_block(&self) -> Result<()> {
571 pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
572 }
573
574 pub fn thread_unblock(&self) -> Result<()> {
576 pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
577 }
578
579 pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
581 let mut oldmask = mem::MaybeUninit::uninit();
582 do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
583 Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
584 }
585
586 #[cfg(not(target_os = "redox"))] pub fn wait(&self) -> Result<Signal> {
590 use std::convert::TryFrom;
591
592 let mut signum = mem::MaybeUninit::uninit();
593 let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
594
595 Errno::result(res).map(|_| unsafe {
596 Signal::try_from(signum.assume_init()).unwrap()
597 })
598 }
599
600 #[cfg(any(
609 bsd,
610 linux_android,
611 solarish,
612 target_os = "haiku",
613 target_os = "hurd",
614 target_os = "aix",
615 target_os = "fuchsia"
616 ))]
617 #[doc(alias("sigsuspend"))]
618 pub fn suspend(&self) -> Result<()> {
619 let res = unsafe {
620 libc::sigsuspend(&self.sigset as *const libc::sigset_t)
621 };
622 match Errno::result(res).map(drop) {
623 Err(Errno::EINTR) => Ok(()),
624 Err(e) => Err(e),
625 Ok(_) => unreachable!("because this syscall always returns -1 if returns"),
626 }
627 }
628
629 pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet {
639 SigSet { sigset }
640 }
641}
642
643impl From<Signal> for SigSet {
644 fn from(signal: Signal) -> SigSet {
645 let mut sigset = SigSet::empty();
646 sigset.add(signal);
647 sigset
648 }
649}
650
651impl BitOr for Signal {
652 type Output = SigSet;
653
654 fn bitor(self, rhs: Self) -> Self::Output {
655 let mut sigset = SigSet::empty();
656 sigset.add(self);
657 sigset.add(rhs);
658 sigset
659 }
660}
661
662impl BitOr<Signal> for SigSet {
663 type Output = SigSet;
664
665 fn bitor(mut self, rhs: Signal) -> Self::Output {
666 self.add(rhs);
667 self
668 }
669}
670
671impl BitOr for SigSet {
672 type Output = Self;
673
674 fn bitor(self, rhs: Self) -> Self::Output {
675 self.iter().chain(rhs.iter()).collect()
676 }
677}
678
679impl AsRef<libc::sigset_t> for SigSet {
680 fn as_ref(&self) -> &libc::sigset_t {
681 &self.sigset
682 }
683}
684
685impl Extend<Signal> for SigSet {
687 fn extend<T>(&mut self, iter: T)
688 where T: IntoIterator<Item = Signal> {
689 for signal in iter {
690 self.add(signal);
691 }
692 }
693}
694
695impl FromIterator<Signal> for SigSet {
696 fn from_iter<T>(iter: T) -> Self
697 where T: IntoIterator<Item = Signal> {
698 let mut sigset = SigSet::empty();
699 sigset.extend(iter);
700 sigset
701 }
702}
703
704impl PartialEq for SigSet {
705 fn eq(&self, other: &Self) -> bool {
706 for signal in Signal::iterator() {
707 if self.contains(signal) != other.contains(signal) {
708 return false;
709 }
710 }
711 true
712 }
713}
714
715impl Hash for SigSet {
716 fn hash<H: Hasher>(&self, state: &mut H) {
717 for signal in Signal::iterator() {
718 if self.contains(signal) {
719 signal.hash(state);
720 }
721 }
722 }
723}
724
725#[derive(Clone, Debug)]
729pub struct SigSetIter<'a> {
730 sigset: &'a SigSet,
731 inner: SignalIterator,
732}
733
734impl Iterator for SigSetIter<'_> {
735 type Item = Signal;
736 fn next(&mut self) -> Option<Signal> {
737 loop {
738 match self.inner.next() {
739 None => return None,
740 Some(signal) if self.sigset.contains(signal) => return Some(signal),
741 Some(_signal) => continue,
742 }
743 }
744 }
745}
746
747impl<'a> IntoIterator for &'a SigSet {
748 type Item = Signal;
749 type IntoIter = SigSetIter<'a>;
750 fn into_iter(self) -> Self::IntoIter {
751 SigSetIter { sigset: self, inner: Signal::iterator() }
752 }
753}
754
755#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
757pub enum SigHandler {
758 SigDfl,
760 SigIgn,
762 Handler(extern "C" fn(libc::c_int)),
764 #[cfg(not(target_os = "redox"))]
767 SigAction(extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
768}
769
770#[repr(transparent)]
772#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
773pub struct SigAction {
774 sigaction: libc::sigaction
775}
776
777impl From<SigAction> for libc::sigaction {
778 fn from(value: SigAction) -> libc::sigaction {
779 value.sigaction
780 }
781}
782
783impl SigAction {
784 pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
790 unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
791 unsafe {
792 (*p).sa_sigaction = match handler {
793 SigHandler::SigDfl => libc::SIG_DFL,
794 SigHandler::SigIgn => libc::SIG_IGN,
795 SigHandler::Handler(f) => f as *const extern "C" fn(libc::c_int) as usize,
796 #[cfg(not(target_os = "redox"))]
797 SigHandler::SigAction(f) => f as *const extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
798 };
799 }
800 }
801
802 let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
803 unsafe {
804 let p = s.as_mut_ptr();
805 install_sig(p, handler);
806 (*p).sa_flags = match handler {
807 #[cfg(not(target_os = "redox"))]
808 SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
809 _ => (flags - SaFlags::SA_SIGINFO).bits(),
810 };
811 (*p).sa_mask = mask.sigset;
812
813 SigAction { sigaction: s.assume_init() }
814 }
815 }
816
817 pub fn flags(&self) -> SaFlags {
819 SaFlags::from_bits_truncate(self.sigaction.sa_flags)
820 }
821
822 pub fn mask(&self) -> SigSet {
825 SigSet { sigset: self.sigaction.sa_mask }
826 }
827
828 pub fn handler(&self) -> SigHandler {
830 match self.sigaction.sa_sigaction {
831 libc::SIG_DFL => SigHandler::SigDfl,
832 libc::SIG_IGN => SigHandler::SigIgn,
833 #[cfg(not(target_os = "redox"))]
834 p if self.flags().contains(SaFlags::SA_SIGINFO) =>
835 SigHandler::SigAction(
836 unsafe{
843 *(&p as *const usize
844 as *const extern "C" fn(_, _, _))
845 }
846 as extern "C" fn(_, _, _)),
847 p => SigHandler::Handler(
848 unsafe{
855 *(&p as *const usize
856 as *const extern "C" fn(libc::c_int))
857 }
858 as extern "C" fn(libc::c_int)),
859 }
860 }
861}
862
863pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
881 let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
882
883 let res = unsafe { libc::sigaction(signal as libc::c_int,
884 &sigaction.sigaction as *const libc::sigaction,
885 oldact.as_mut_ptr()) };
886
887 Errno::result(res).map(|_| SigAction { sigaction: unsafe { oldact.assume_init() } })
888}
889
890pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
943 let signal = signal as libc::c_int;
944 let res = match handler {
945 SigHandler::SigDfl => unsafe { libc::signal(signal, libc::SIG_DFL) },
946 SigHandler::SigIgn => unsafe { libc::signal(signal, libc::SIG_IGN) },
947 SigHandler::Handler(handler) => unsafe { libc::signal(signal, handler as libc::sighandler_t) },
948 #[cfg(not(target_os = "redox"))]
949 SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
950 };
951 Errno::result(res).map(|oldhandler| {
952 match oldhandler {
953 libc::SIG_DFL => SigHandler::SigDfl,
954 libc::SIG_IGN => SigHandler::SigIgn,
955 p => SigHandler::Handler(
956 unsafe { *(&p as *const usize as *const extern "C" fn(libc::c_int)) } as extern "C" fn(libc::c_int)),
957 }
958 })
959}
960
961fn do_pthread_sigmask(how: SigmaskHow,
962 set: Option<&SigSet>,
963 oldset: Option<*mut libc::sigset_t>) -> Result<()> {
964 if set.is_none() && oldset.is_none() {
965 return Ok(())
966 }
967
968 let res = unsafe {
969 libc::pthread_sigmask(how as libc::c_int,
971 set.map_or_else(ptr::null::<libc::sigset_t>,
972 |s| &s.sigset as *const libc::sigset_t),
973 oldset.unwrap_or(ptr::null_mut())
974 )
975 };
976
977 Errno::result(res).map(drop)
978}
979
980pub fn pthread_sigmask(how: SigmaskHow,
996 set: Option<&SigSet>,
997 oldset: Option<&mut SigSet>) -> Result<()>
998{
999 do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
1000}
1001
1002pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
1007 if set.is_none() && oldset.is_none() {
1008 return Ok(())
1009 }
1010
1011 let res = unsafe {
1012 libc::sigprocmask(how as libc::c_int,
1014 set.map_or_else(ptr::null::<libc::sigset_t>,
1015 |s| &s.sigset as *const libc::sigset_t),
1016 oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
1017 |os| &mut os.sigset as *mut libc::sigset_t))
1018 };
1019
1020 Errno::result(res).map(drop)
1021}
1022
1023#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
1032#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
1033pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
1043 let res = unsafe { libc::kill(pid.into(),
1044 match signal.into() {
1045 Some(s) => s as libc::c_int,
1046 None => 0,
1047 }) };
1048
1049 Errno::result(res).map(drop)
1050}
1051
1052#[cfg(not(target_os = "fuchsia"))]
1063pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
1064 let res = unsafe { libc::killpg(pgrp.into(),
1065 match signal.into() {
1066 Some(s) => s as libc::c_int,
1067 None => 0,
1068 }) };
1069
1070 Errno::result(res).map(drop)
1071}
1072
1073pub fn raise(signal: Signal) -> Result<()> {
1077 let res = unsafe { libc::raise(signal as libc::c_int) };
1078
1079 Errno::result(res).map(drop)
1080}
1081}
1082
1083feature! {
1084#![any(feature = "aio", feature = "signal")]
1085
1086#[cfg(target_os = "freebsd")]
1088pub type type_of_thread_id = libc::lwpid_t;
1089#[cfg(all(not(target_os = "hurd"), any(target_env = "gnu", target_env = "uclibc")))]
1091pub type type_of_thread_id = libc::pid_t;
1092
1093#[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))]
1098#[derive(Clone, Copy, Debug)]
1099pub enum SigevNotify<'fd> {
1100 SigevNone,
1102 SigevSignal {
1104 signal: Signal,
1106 si_value: libc::intptr_t
1109 },
1110 #[cfg(freebsdlike)]
1113 SigevKevent {
1114 kq: std::os::fd::BorrowedFd<'fd>,
1116 udata: libc::intptr_t
1118 },
1119 #[cfg(target_os = "freebsd")]
1121 #[cfg(feature = "event")]
1122 SigevKeventFlags {
1123 kq: std::os::fd::BorrowedFd<'fd>,
1125 udata: libc::intptr_t,
1127 flags: crate::sys::event::EvFlags
1129 },
1130 #[cfg(any(
1132 target_os = "freebsd",
1133 target_env = "gnu",
1134 target_env = "uclibc",
1135 ))]
1136 SigevThreadId {
1137 signal: Signal,
1139 thread_id: type_of_thread_id,
1141 si_value: libc::intptr_t
1144 },
1145 #[doc(hidden)]
1151 #[cfg(not(freebsdlike))]
1152 _Unreachable(&'fd std::convert::Infallible),
1153}
1154}
1155
1156#[cfg(not(any(
1157 target_os = "fuchsia",
1158 target_os = "hurd",
1159 target_os = "openbsd",
1160 target_os = "redox"
1161)))]
1162mod sigevent {
1163 feature! {
1164 #![any(feature = "aio", feature = "signal")]
1165
1166 use std::mem;
1167 use super::SigevNotify;
1168
1169 #[cfg(target_os = "freebsd")]
1170 pub(crate) use ffi::sigevent as libc_sigevent;
1171 #[cfg(not(target_os = "freebsd"))]
1172 pub(crate) use libc::sigevent as libc_sigevent;
1173
1174 #[cfg(target_os = "freebsd")]
1186 mod ffi {
1187 use std::{fmt, hash};
1188
1189 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1190 #[repr(C)]
1191 pub struct __c_anonymous_sigev_thread {
1192 pub _function: *mut libc::c_void, pub _attribute: *mut libc::pthread_attr_t,
1194 }
1195 #[derive(Clone, Copy)]
1196 #[allow(missing_debug_implementations)]
1199 #[repr(C)]
1200 pub union __c_anonymous_sigev_un {
1201 pub _threadid: libc::__lwpid_t,
1202 pub _sigev_thread: __c_anonymous_sigev_thread,
1203 pub _kevent_flags: libc::c_ushort,
1204 __spare__: [libc::c_long; 8],
1205 }
1206
1207 #[derive(Clone, Copy)]
1208 #[repr(C)]
1209 pub struct sigevent {
1210 pub sigev_notify: libc::c_int,
1211 pub sigev_signo: libc::c_int,
1212 pub sigev_value: libc::sigval,
1213 pub _sigev_un: __c_anonymous_sigev_un,
1214 }
1215
1216 impl fmt::Debug for sigevent {
1217 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1218 let mut ds = f.debug_struct("sigevent");
1219 ds.field("sigev_notify", &self.sigev_notify)
1220 .field("sigev_signo", &self.sigev_signo)
1221 .field("sigev_value", &self.sigev_value);
1222 unsafe {
1224 match self.sigev_notify {
1225 libc::SIGEV_KEVENT => {
1226 ds.field("sigev_notify_kevent_flags", &self._sigev_un._kevent_flags);
1227 }
1228 libc::SIGEV_THREAD_ID => {
1229 ds.field("sigev_notify_thread_id", &self._sigev_un._threadid);
1230 }
1231 libc::SIGEV_THREAD => {
1232 ds.field("sigev_notify_function", &self._sigev_un._sigev_thread._function);
1233 ds.field("sigev_notify_attributes", &self._sigev_un._sigev_thread._attribute);
1234 }
1235 _ => ()
1236 };
1237 }
1238 ds.finish()
1239 }
1240 }
1241
1242 impl PartialEq for sigevent {
1243 fn eq(&self, other: &Self) -> bool {
1244 let mut equals = self.sigev_notify == other.sigev_notify;
1245 equals &= self.sigev_signo == other.sigev_signo;
1246 equals &= self.sigev_value == other.sigev_value;
1247 unsafe {
1249 match self.sigev_notify {
1250 libc::SIGEV_KEVENT => {
1251 equals &= self._sigev_un._kevent_flags == other._sigev_un._kevent_flags;
1252 }
1253 libc::SIGEV_THREAD_ID => {
1254 equals &= self._sigev_un._threadid == other._sigev_un._threadid;
1255 }
1256 libc::SIGEV_THREAD => {
1257 equals &= self._sigev_un._sigev_thread == other._sigev_un._sigev_thread;
1258 }
1259 _ => ()
1260 }
1261 }
1262 equals
1263 }
1264 }
1265
1266 impl Eq for sigevent {}
1267
1268 impl hash::Hash for sigevent {
1269 fn hash<H: hash::Hasher>(&self, s: &mut H) {
1270 self.sigev_notify.hash(s);
1271 self.sigev_signo.hash(s);
1272 self.sigev_value.hash(s);
1273 unsafe {
1275 match self.sigev_notify {
1276 libc::SIGEV_KEVENT => {
1277 self._sigev_un._kevent_flags.hash(s);
1278 }
1279 libc::SIGEV_THREAD_ID => {
1280 self._sigev_un._threadid.hash(s);
1281 }
1282 libc::SIGEV_THREAD => {
1283 self._sigev_un._sigev_thread.hash(s);
1284 }
1285 _ => ()
1286 }
1287 }
1288 }
1289 }
1290 }
1291
1292 #[repr(C)]
1295 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1296 #[allow(missing_copy_implementations)]
1298 pub struct SigEvent {
1299 sigevent: libc_sigevent
1300 }
1301
1302 impl SigEvent {
1303 pub fn new(sigev_notify: SigevNotify) -> SigEvent {
1317 let mut sev: libc_sigevent = unsafe { mem::zeroed() };
1318 match sigev_notify {
1319 SigevNotify::SigevNone => {
1320 sev.sigev_notify = libc::SIGEV_NONE;
1321 },
1322 SigevNotify::SigevSignal{signal, si_value} => {
1323 sev.sigev_notify = libc::SIGEV_SIGNAL;
1324 sev.sigev_signo = signal as libc::c_int;
1325 sev.sigev_value.sival_ptr = si_value as *mut libc::c_void
1326 },
1327 #[cfg(freebsdlike)]
1328 SigevNotify::SigevKevent{kq, udata} => {
1329 use std::os::fd::AsRawFd;
1330
1331 sev.sigev_notify = libc::SIGEV_KEVENT;
1332 sev.sigev_signo = kq.as_raw_fd();
1333 sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
1334 },
1335 #[cfg(target_os = "freebsd")]
1336 #[cfg(feature = "event")]
1337 SigevNotify::SigevKeventFlags{kq, udata, flags} => {
1338 use std::os::fd::AsRawFd;
1339
1340 sev.sigev_notify = libc::SIGEV_KEVENT;
1341 sev.sigev_signo = kq.as_raw_fd();
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 #[cfg(not(freebsdlike))]
1360 SigevNotify::_Unreachable(_) => unreachable!("This variant could never be constructed")
1361 }
1362 SigEvent{sigevent: sev}
1363 }
1364
1365 #[cfg(target_os = "freebsd")]
1367 pub fn sigevent(&self) -> libc::sigevent {
1368 unsafe {
1371 mem::transmute::<libc_sigevent, libc::sigevent>(self.sigevent)
1372 }
1373 }
1374
1375 #[cfg(not(target_os = "freebsd"))]
1377 pub fn sigevent(&self) -> libc::sigevent {
1378 self.sigevent
1379 }
1380
1381 #[cfg(target_os = "freebsd")]
1383 pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1384 &mut self.sigevent as *mut libc_sigevent as *mut libc::sigevent
1387 }
1388
1389 #[cfg(not(target_os = "freebsd"))]
1391 pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1392 &mut self.sigevent
1393 }
1394 }
1395
1396 impl From<&'_ libc::sigevent> for SigEvent {
1397 #[cfg(target_os = "freebsd")]
1398 fn from(sigevent: &libc::sigevent) -> Self {
1399 let sigevent = unsafe {
1402 mem::transmute::<libc::sigevent, libc_sigevent>(*sigevent)
1403 };
1404 SigEvent{ sigevent }
1405 }
1406 #[cfg(not(target_os = "freebsd"))]
1407 fn from(sigevent: &libc::sigevent) -> Self {
1408 SigEvent{ sigevent: *sigevent }
1409 }
1410 }
1411 }
1412}