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_env = "uclibc")] {
430 type SaFlags_t = libc::c_ulong;
431 } else {
432 type SaFlags_t = libc::c_int;
433 }
434}
435}
436
437#[cfg(feature = "signal")]
438libc_bitflags! {
439 #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
441 pub struct SaFlags: SaFlags_t {
442 SA_NOCLDSTOP as SaFlags_t;
446 #[cfg(not(target_os = "hurd"))]
449 SA_NOCLDWAIT as SaFlags_t;
450 SA_NODEFER as SaFlags_t;
453 SA_ONSTACK as SaFlags_t;
456 SA_RESETHAND as SaFlags_t;
459 SA_RESTART as SaFlags_t;
462 SA_SIGINFO as SaFlags_t;
464 }
465}
466
467#[cfg(feature = "signal")]
468libc_enum! {
469 #[repr(i32)]
471 #[non_exhaustive]
472 #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
473 pub enum SigmaskHow {
474 SIG_BLOCK,
476 SIG_UNBLOCK,
479 SIG_SETMASK,
481 }
482}
483
484feature! {
485#![feature = "signal"]
486
487use crate::unistd::Pid;
488use std::iter::Extend;
489use std::iter::FromIterator;
490use std::iter::IntoIterator;
491
492#[repr(transparent)]
496#[derive(Clone, Copy, Debug, Eq)]
497pub struct SigSet {
498 sigset: libc::sigset_t
499}
500
501impl SigSet {
502 #[doc(alias("sigfillset"))]
504 pub fn all() -> SigSet {
505 let mut sigset = mem::MaybeUninit::uninit();
506 let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
507
508 unsafe{ SigSet { sigset: sigset.assume_init() } }
509 }
510
511 #[doc(alias("sigemptyset"))]
513 pub fn empty() -> SigSet {
514 let mut sigset = mem::MaybeUninit::uninit();
515 let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
516
517 unsafe{ SigSet { sigset: sigset.assume_init() } }
518 }
519
520 #[doc(alias("sigaddset"))]
522 pub fn add(&mut self, signal: Signal) {
523 unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
524 }
525
526 #[doc(alias("sigemptyset"))]
528 pub fn clear(&mut self) {
529 unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
530 }
531
532 #[doc(alias("sigdelset"))]
534 pub fn remove(&mut self, signal: Signal) {
535 unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
536 }
537
538 #[doc(alias("sigismember"))]
540 pub fn contains(&self, signal: Signal) -> bool {
541 let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
542
543 match res {
544 1 => true,
545 0 => false,
546 _ => unreachable!("unexpected value from sigismember"),
547 }
548 }
549
550 pub fn iter(&self) -> SigSetIter<'_> {
552 self.into_iter()
553 }
554
555 pub fn thread_get_mask() -> Result<SigSet> {
557 let mut oldmask = mem::MaybeUninit::uninit();
558 do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
559 Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
560 }
561
562 pub fn thread_set_mask(&self) -> Result<()> {
564 pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
565 }
566
567 pub fn thread_block(&self) -> Result<()> {
569 pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
570 }
571
572 pub fn thread_unblock(&self) -> Result<()> {
574 pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
575 }
576
577 pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
579 let mut oldmask = mem::MaybeUninit::uninit();
580 do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
581 Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
582 }
583
584 #[cfg(not(target_os = "redox"))] pub fn wait(&self) -> Result<Signal> {
588 use std::convert::TryFrom;
589
590 let mut signum = mem::MaybeUninit::uninit();
591 let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
592
593 Errno::result(res).map(|_| unsafe {
594 Signal::try_from(signum.assume_init()).unwrap()
595 })
596 }
597
598 #[cfg(any(
607 bsd,
608 linux_android,
609 solarish,
610 target_os = "haiku",
611 target_os = "hurd",
612 target_os = "aix",
613 target_os = "fuchsia"
614 ))]
615 #[doc(alias("sigsuspend"))]
616 pub fn suspend(&self) -> Result<()> {
617 let res = unsafe {
618 libc::sigsuspend(&self.sigset as *const libc::sigset_t)
619 };
620 match Errno::result(res).map(drop) {
621 Err(Errno::EINTR) => Ok(()),
622 Err(e) => Err(e),
623 Ok(_) => unreachable!("because this syscall always returns -1 if returns"),
624 }
625 }
626
627 pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet {
637 SigSet { sigset }
638 }
639}
640
641impl From<Signal> for SigSet {
642 fn from(signal: Signal) -> SigSet {
643 let mut sigset = SigSet::empty();
644 sigset.add(signal);
645 sigset
646 }
647}
648
649impl BitOr for Signal {
650 type Output = SigSet;
651
652 fn bitor(self, rhs: Self) -> Self::Output {
653 let mut sigset = SigSet::empty();
654 sigset.add(self);
655 sigset.add(rhs);
656 sigset
657 }
658}
659
660impl BitOr<Signal> for SigSet {
661 type Output = SigSet;
662
663 fn bitor(mut self, rhs: Signal) -> Self::Output {
664 self.add(rhs);
665 self
666 }
667}
668
669impl BitOr for SigSet {
670 type Output = Self;
671
672 fn bitor(self, rhs: Self) -> Self::Output {
673 self.iter().chain(rhs.iter()).collect()
674 }
675}
676
677impl AsRef<libc::sigset_t> for SigSet {
678 fn as_ref(&self) -> &libc::sigset_t {
679 &self.sigset
680 }
681}
682
683impl Extend<Signal> for SigSet {
685 fn extend<T>(&mut self, iter: T)
686 where T: IntoIterator<Item = Signal> {
687 for signal in iter {
688 self.add(signal);
689 }
690 }
691}
692
693impl FromIterator<Signal> for SigSet {
694 fn from_iter<T>(iter: T) -> Self
695 where T: IntoIterator<Item = Signal> {
696 let mut sigset = SigSet::empty();
697 sigset.extend(iter);
698 sigset
699 }
700}
701
702impl PartialEq for SigSet {
703 fn eq(&self, other: &Self) -> bool {
704 for signal in Signal::iterator() {
705 if self.contains(signal) != other.contains(signal) {
706 return false;
707 }
708 }
709 true
710 }
711}
712
713impl Hash for SigSet {
714 fn hash<H: Hasher>(&self, state: &mut H) {
715 for signal in Signal::iterator() {
716 if self.contains(signal) {
717 signal.hash(state);
718 }
719 }
720 }
721}
722
723#[derive(Clone, Debug)]
727pub struct SigSetIter<'a> {
728 sigset: &'a SigSet,
729 inner: SignalIterator,
730}
731
732impl Iterator for SigSetIter<'_> {
733 type Item = Signal;
734 fn next(&mut self) -> Option<Signal> {
735 loop {
736 match self.inner.next() {
737 None => return None,
738 Some(signal) if self.sigset.contains(signal) => return Some(signal),
739 Some(_signal) => continue,
740 }
741 }
742 }
743}
744
745impl<'a> IntoIterator for &'a SigSet {
746 type Item = Signal;
747 type IntoIter = SigSetIter<'a>;
748 fn into_iter(self) -> Self::IntoIter {
749 SigSetIter { sigset: self, inner: Signal::iterator() }
750 }
751}
752
753#[derive(Clone, Copy, Debug, Hash)]
785pub enum SigHandler {
786 SigDfl,
788 SigIgn,
790 Handler(extern "C" fn(libc::c_int)),
792 #[cfg(not(target_os = "redox"))]
795 SigAction(extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
796}
797
798#[repr(transparent)]
822#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
823pub struct SigAction {
824 sigaction: libc::sigaction
825}
826
827impl From<SigAction> for libc::sigaction {
828 fn from(value: SigAction) -> libc::sigaction {
829 value.sigaction
830 }
831}
832
833impl SigAction {
834 pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
840 unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
841 unsafe {
842 (*p).sa_sigaction = match handler {
843 SigHandler::SigDfl => libc::SIG_DFL,
844 SigHandler::SigIgn => libc::SIG_IGN,
845 SigHandler::Handler(f) => f as *const extern "C" fn(libc::c_int) as usize,
846 #[cfg(not(target_os = "redox"))]
847 SigHandler::SigAction(f) => f as *const extern "C" fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
848 };
849 }
850 }
851
852 let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
853 unsafe {
854 let p = s.as_mut_ptr();
855 install_sig(p, handler);
856 (*p).sa_flags = match handler {
857 #[cfg(not(target_os = "redox"))]
858 SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
859 _ => (flags - SaFlags::SA_SIGINFO).bits(),
860 };
861 (*p).sa_mask = mask.sigset;
862
863 SigAction { sigaction: s.assume_init() }
864 }
865 }
866
867 pub fn flags(&self) -> SaFlags {
869 SaFlags::from_bits_truncate(self.sigaction.sa_flags)
870 }
871
872 pub fn mask(&self) -> SigSet {
875 SigSet { sigset: self.sigaction.sa_mask }
876 }
877
878 pub fn handler(&self) -> SigHandler {
880 match self.sigaction.sa_sigaction {
881 libc::SIG_DFL => SigHandler::SigDfl,
882 libc::SIG_IGN => SigHandler::SigIgn,
883 #[cfg(not(target_os = "redox"))]
884 p if self.flags().contains(SaFlags::SA_SIGINFO) =>
885 SigHandler::SigAction(
886 unsafe{
893 *(&p as *const usize
894 as *const extern "C" fn(_, _, _))
895 }
896 as extern "C" fn(_, _, _)),
897 p => SigHandler::Handler(
898 unsafe{
905 *(&p as *const usize
906 as *const extern "C" fn(libc::c_int))
907 }
908 as extern "C" fn(libc::c_int)),
909 }
910 }
911}
912
913pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
931 let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
932
933 let res = unsafe { libc::sigaction(signal as libc::c_int,
934 &sigaction.sigaction as *const libc::sigaction,
935 oldact.as_mut_ptr()) };
936
937 Errno::result(res).map(|_| SigAction { sigaction: unsafe { oldact.assume_init() } })
938}
939
940pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
993 let signal = signal as libc::c_int;
994 let res = match handler {
995 SigHandler::SigDfl => unsafe { libc::signal(signal, libc::SIG_DFL) },
996 SigHandler::SigIgn => unsafe { libc::signal(signal, libc::SIG_IGN) },
997 SigHandler::Handler(handler) => unsafe { libc::signal(signal, handler as libc::sighandler_t) },
998 #[cfg(not(target_os = "redox"))]
999 SigHandler::SigAction(_) => return Err(Errno::ENOTSUP),
1000 };
1001 Errno::result(res).map(|oldhandler| {
1002 match oldhandler {
1003 libc::SIG_DFL => SigHandler::SigDfl,
1004 libc::SIG_IGN => SigHandler::SigIgn,
1005 p => SigHandler::Handler(
1006 unsafe { *(&p as *const usize as *const extern "C" fn(libc::c_int)) } as extern "C" fn(libc::c_int)),
1007 }
1008 })
1009}
1010
1011fn do_pthread_sigmask(how: SigmaskHow,
1012 set: Option<&SigSet>,
1013 oldset: Option<*mut libc::sigset_t>) -> Result<()> {
1014 if set.is_none() && oldset.is_none() {
1015 return Ok(())
1016 }
1017
1018 let res = unsafe {
1019 libc::pthread_sigmask(how as libc::c_int,
1021 set.map_or_else(ptr::null::<libc::sigset_t>,
1022 |s| &s.sigset as *const libc::sigset_t),
1023 oldset.unwrap_or(ptr::null_mut())
1024 )
1025 };
1026
1027 Errno::result(res).map(drop)
1028}
1029
1030pub fn pthread_sigmask(how: SigmaskHow,
1046 set: Option<&SigSet>,
1047 oldset: Option<&mut SigSet>) -> Result<()>
1048{
1049 do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
1050}
1051
1052pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
1057 if set.is_none() && oldset.is_none() {
1058 return Ok(())
1059 }
1060
1061 let res = unsafe {
1062 libc::sigprocmask(how as libc::c_int,
1064 set.map_or_else(ptr::null::<libc::sigset_t>,
1065 |s| &s.sigset as *const libc::sigset_t),
1066 oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
1067 |os| &mut os.sigset as *mut libc::sigset_t))
1068 };
1069
1070 Errno::result(res).map(drop)
1071}
1072
1073#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
1082#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
1083pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
1093 let res = unsafe { libc::kill(pid.into(),
1094 match signal.into() {
1095 Some(s) => s as libc::c_int,
1096 None => 0,
1097 }) };
1098
1099 Errno::result(res).map(drop)
1100}
1101
1102#[cfg(not(target_os = "fuchsia"))]
1113pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
1114 let res = unsafe { libc::killpg(pgrp.into(),
1115 match signal.into() {
1116 Some(s) => s as libc::c_int,
1117 None => 0,
1118 }) };
1119
1120 Errno::result(res).map(drop)
1121}
1122
1123pub fn raise(signal: Signal) -> Result<()> {
1127 let res = unsafe { libc::raise(signal as libc::c_int) };
1128
1129 Errno::result(res).map(drop)
1130}
1131}
1132
1133feature! {
1134#![any(feature = "aio", feature = "signal")]
1135
1136#[cfg(target_os = "freebsd")]
1138pub type type_of_thread_id = libc::lwpid_t;
1139#[cfg(all(not(target_os = "hurd"), any(target_env = "gnu", target_env = "uclibc")))]
1141pub type type_of_thread_id = libc::pid_t;
1142
1143#[cfg(not(any(target_os = "fuchsia", target_os = "hurd", target_os = "openbsd", target_os = "redox")))]
1148#[derive(Clone, Copy, Debug)]
1149pub enum SigevNotify<'fd> {
1150 SigevNone,
1152 SigevSignal {
1154 signal: Signal,
1156 si_value: libc::intptr_t
1159 },
1160 #[cfg(freebsdlike)]
1163 SigevKevent {
1164 kq: std::os::fd::BorrowedFd<'fd>,
1166 udata: libc::intptr_t
1168 },
1169 #[cfg(target_os = "freebsd")]
1171 #[cfg(feature = "event")]
1172 SigevKeventFlags {
1173 kq: std::os::fd::BorrowedFd<'fd>,
1175 udata: libc::intptr_t,
1177 flags: crate::sys::event::EvFlags
1179 },
1180 #[cfg(any(
1182 target_os = "freebsd",
1183 target_env = "gnu",
1184 target_env = "uclibc",
1185 ))]
1186 SigevThreadId {
1187 signal: Signal,
1189 thread_id: type_of_thread_id,
1191 si_value: libc::intptr_t
1194 },
1195 #[doc(hidden)]
1201 #[cfg(not(freebsdlike))]
1202 _Unreachable(&'fd std::convert::Infallible),
1203}
1204}
1205
1206#[cfg(not(any(
1207 target_os = "fuchsia",
1208 target_os = "hurd",
1209 target_os = "openbsd",
1210 target_os = "redox"
1211)))]
1212mod sigevent {
1213 feature! {
1214 #![any(feature = "aio", feature = "signal")]
1215
1216 use std::mem;
1217 use super::SigevNotify;
1218
1219 #[cfg(target_os = "freebsd")]
1220 pub(crate) use ffi::sigevent as libc_sigevent;
1221 #[cfg(not(target_os = "freebsd"))]
1222 pub(crate) use libc::sigevent as libc_sigevent;
1223
1224 #[cfg(target_os = "freebsd")]
1236 mod ffi {
1237 use std::{fmt, hash};
1238
1239 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1240 #[repr(C)]
1241 pub struct __c_anonymous_sigev_thread {
1242 pub _function: *mut libc::c_void, pub _attribute: *mut libc::pthread_attr_t,
1244 }
1245 #[derive(Clone, Copy)]
1246 #[allow(missing_debug_implementations)]
1249 #[repr(C)]
1250 pub union __c_anonymous_sigev_un {
1251 pub _threadid: libc::__lwpid_t,
1252 pub _sigev_thread: __c_anonymous_sigev_thread,
1253 pub _kevent_flags: libc::c_ushort,
1254 __spare__: [libc::c_long; 8],
1255 }
1256
1257 #[derive(Clone, Copy)]
1258 #[repr(C)]
1259 pub struct sigevent {
1260 pub sigev_notify: libc::c_int,
1261 pub sigev_signo: libc::c_int,
1262 pub sigev_value: libc::sigval,
1263 pub _sigev_un: __c_anonymous_sigev_un,
1264 }
1265
1266 impl fmt::Debug for sigevent {
1267 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1268 let mut ds = f.debug_struct("sigevent");
1269 ds.field("sigev_notify", &self.sigev_notify)
1270 .field("sigev_signo", &self.sigev_signo)
1271 .field("sigev_value", &self.sigev_value);
1272 unsafe {
1274 match self.sigev_notify {
1275 libc::SIGEV_KEVENT => {
1276 ds.field("sigev_notify_kevent_flags", &self._sigev_un._kevent_flags);
1277 }
1278 libc::SIGEV_THREAD_ID => {
1279 ds.field("sigev_notify_thread_id", &self._sigev_un._threadid);
1280 }
1281 libc::SIGEV_THREAD => {
1282 ds.field("sigev_notify_function", &self._sigev_un._sigev_thread._function);
1283 ds.field("sigev_notify_attributes", &self._sigev_un._sigev_thread._attribute);
1284 }
1285 _ => ()
1286 };
1287 }
1288 ds.finish()
1289 }
1290 }
1291
1292 impl PartialEq for sigevent {
1293 fn eq(&self, other: &Self) -> bool {
1294 let mut equals = self.sigev_notify == other.sigev_notify;
1295 equals &= self.sigev_signo == other.sigev_signo;
1296 equals &= self.sigev_value == other.sigev_value;
1297 unsafe {
1299 match self.sigev_notify {
1300 libc::SIGEV_KEVENT => {
1301 equals &= self._sigev_un._kevent_flags == other._sigev_un._kevent_flags;
1302 }
1303 libc::SIGEV_THREAD_ID => {
1304 equals &= self._sigev_un._threadid == other._sigev_un._threadid;
1305 }
1306 libc::SIGEV_THREAD => {
1307 equals &= self._sigev_un._sigev_thread == other._sigev_un._sigev_thread;
1308 }
1309 _ => ()
1310 }
1311 }
1312 equals
1313 }
1314 }
1315
1316 impl Eq for sigevent {}
1317
1318 impl hash::Hash for sigevent {
1319 fn hash<H: hash::Hasher>(&self, s: &mut H) {
1320 self.sigev_notify.hash(s);
1321 self.sigev_signo.hash(s);
1322 self.sigev_value.hash(s);
1323 unsafe {
1325 match self.sigev_notify {
1326 libc::SIGEV_KEVENT => {
1327 self._sigev_un._kevent_flags.hash(s);
1328 }
1329 libc::SIGEV_THREAD_ID => {
1330 self._sigev_un._threadid.hash(s);
1331 }
1332 libc::SIGEV_THREAD => {
1333 self._sigev_un._sigev_thread.hash(s);
1334 }
1335 _ => ()
1336 }
1337 }
1338 }
1339 }
1340 }
1341
1342 #[repr(C)]
1345 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1346 #[allow(missing_copy_implementations)]
1348 pub struct SigEvent {
1349 sigevent: libc_sigevent
1350 }
1351
1352 impl SigEvent {
1353 pub fn new(sigev_notify: SigevNotify) -> SigEvent {
1367 let mut sev: libc_sigevent = unsafe { mem::zeroed() };
1368 match sigev_notify {
1369 SigevNotify::SigevNone => {
1370 sev.sigev_notify = libc::SIGEV_NONE;
1371 },
1372 SigevNotify::SigevSignal{signal, si_value} => {
1373 sev.sigev_notify = libc::SIGEV_SIGNAL;
1374 sev.sigev_signo = signal as libc::c_int;
1375 sev.sigev_value.sival_ptr = si_value as *mut libc::c_void
1376 },
1377 #[cfg(freebsdlike)]
1378 SigevNotify::SigevKevent{kq, udata} => {
1379 use std::os::fd::AsRawFd;
1380
1381 sev.sigev_notify = libc::SIGEV_KEVENT;
1382 sev.sigev_signo = kq.as_raw_fd();
1383 sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
1384 },
1385 #[cfg(target_os = "freebsd")]
1386 #[cfg(feature = "event")]
1387 SigevNotify::SigevKeventFlags{kq, udata, flags} => {
1388 use std::os::fd::AsRawFd;
1389
1390 sev.sigev_notify = libc::SIGEV_KEVENT;
1391 sev.sigev_signo = kq.as_raw_fd();
1392 sev.sigev_value.sival_ptr = udata as *mut libc::c_void;
1393 sev._sigev_un._kevent_flags = flags.bits();
1394 },
1395 #[cfg(target_os = "freebsd")]
1396 SigevNotify::SigevThreadId{signal, thread_id, si_value} => {
1397 sev.sigev_notify = libc::SIGEV_THREAD_ID;
1398 sev.sigev_signo = signal as libc::c_int;
1399 sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
1400 sev._sigev_un._threadid = thread_id;
1401 }
1402 #[cfg(any(target_env = "gnu", target_env = "uclibc"))]
1403 SigevNotify::SigevThreadId{signal, thread_id, si_value} => {
1404 sev.sigev_notify = libc::SIGEV_THREAD_ID;
1405 sev.sigev_signo = signal as libc::c_int;
1406 sev.sigev_value.sival_ptr = si_value as *mut libc::c_void;
1407 sev.sigev_notify_thread_id = thread_id;
1408 }
1409 #[cfg(not(freebsdlike))]
1410 SigevNotify::_Unreachable(_) => unreachable!("This variant could never be constructed")
1411 }
1412 SigEvent{sigevent: sev}
1413 }
1414
1415 #[cfg(target_os = "freebsd")]
1417 pub fn sigevent(&self) -> libc::sigevent {
1418 unsafe {
1421 mem::transmute::<libc_sigevent, libc::sigevent>(self.sigevent)
1422 }
1423 }
1424
1425 #[cfg(not(target_os = "freebsd"))]
1427 pub fn sigevent(&self) -> libc::sigevent {
1428 self.sigevent
1429 }
1430
1431 #[cfg(target_os = "freebsd")]
1433 pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1434 &mut self.sigevent as *mut libc_sigevent as *mut libc::sigevent
1437 }
1438
1439 #[cfg(not(target_os = "freebsd"))]
1441 pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
1442 &mut self.sigevent
1443 }
1444 }
1445
1446 impl From<&'_ libc::sigevent> for SigEvent {
1447 #[cfg(target_os = "freebsd")]
1448 fn from(sigevent: &libc::sigevent) -> Self {
1449 let sigevent = unsafe {
1452 mem::transmute::<libc::sigevent, libc_sigevent>(*sigevent)
1453 };
1454 SigEvent{ sigevent }
1455 }
1456 #[cfg(not(target_os = "freebsd"))]
1457 fn from(sigevent: &libc::sigevent) -> Self {
1458 SigEvent{ sigevent: *sigevent }
1459 }
1460 }
1461 }
1462}