aboutsummaryrefslogtreecommitdiff
path: root/src/sys/signal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/signal.rs')
-rw-r--r--src/sys/signal.rs580
1 files changed, 347 insertions, 233 deletions
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index 61bdc74..d3746e6 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -3,20 +3,22 @@
//! Operating system signals.
-use crate::{Error, Result};
use crate::errno::Errno;
-use crate::unistd::Pid;
-use std::mem;
+use crate::{Error, Result};
+use cfg_if::cfg_if;
use std::fmt;
-use std::str::FromStr;
+use std::mem;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
use std::os::unix::io::RawFd;
use std::ptr;
+use std::str::FromStr;
#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
+#[cfg(any(feature = "aio", feature = "signal"))]
pub use self::sigevent::*;
-libc_enum!{
+#[cfg(any(feature = "aio", feature = "process", feature = "signal"))]
+libc_enum! {
/// Types of operating system signals
// Currently there is only one definition of c_int in libc, as well as only one
// type for signal constants.
@@ -24,6 +26,7 @@ libc_enum!{
// this is not (yet) possible.
#[repr(i32)]
#[non_exhaustive]
+ #[cfg_attr(docsrs, doc(cfg(any(feature = "aio", feature = "signal"))))]
pub enum Signal {
/// Hangup
SIGHUP,
@@ -86,27 +89,33 @@ libc_enum!{
/// Window size changes
SIGWINCH,
/// Input/output possible signal
+ #[cfg(not(target_os = "haiku"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
SIGIO,
#[cfg(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
/// Power failure imminent.
SIGPWR,
/// Bad system call
SIGSYS,
#[cfg(not(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
+ target_os = "redox", target_os = "haiku")))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
/// Emulator trap
SIGEMT,
#[cfg(not(any(target_os = "android", target_os = "emscripten",
target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
+ target_os = "redox", target_os = "haiku")))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
/// Information request
SIGINFO,
}
impl TryFrom<i32>
}
+#[cfg(feature = "signal")]
impl FromStr for Signal {
type Err = Error;
fn from_str(s: &str) -> Result<Signal> {
@@ -126,10 +135,19 @@ impl FromStr for Signal {
"SIGPIPE" => Signal::SIGPIPE,
"SIGALRM" => Signal::SIGALRM,
"SIGTERM" => Signal::SIGTERM,
- #[cfg(all(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"),
- not(any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64"))))]
+ #[cfg(all(
+ any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ),
+ not(any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "sparc64"
+ ))
+ ))]
"SIGSTKFLT" => Signal::SIGSTKFLT,
"SIGCHLD" => Signal::SIGCHLD,
"SIGCONT" => Signal::SIGCONT,
@@ -143,24 +161,40 @@ impl FromStr for Signal {
"SIGVTALRM" => Signal::SIGVTALRM,
"SIGPROF" => Signal::SIGPROF,
"SIGWINCH" => Signal::SIGWINCH,
+ #[cfg(not(target_os = "haiku"))]
"SIGIO" => Signal::SIGIO,
- #[cfg(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ))]
"SIGPWR" => Signal::SIGPWR,
"SIGSYS" => Signal::SIGSYS,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux",
+ target_os = "redox",
+ target_os = "haiku"
+ )))]
"SIGEMT" => Signal::SIGEMT,
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux",
+ target_os = "redox",
+ target_os = "haiku"
+ )))]
"SIGINFO" => Signal::SIGINFO,
_ => return Err(Errno::EINVAL),
})
}
}
+#[cfg(feature = "signal")]
impl Signal {
/// Returns name of signal.
///
@@ -184,9 +218,19 @@ impl Signal {
Signal::SIGPIPE => "SIGPIPE",
Signal::SIGALRM => "SIGALRM",
Signal::SIGTERM => "SIGTERM",
- #[cfg(all(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"),
- not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
+ #[cfg(all(
+ any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ),
+ not(any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "sparc64"
+ ))
+ ))]
Signal::SIGSTKFLT => "SIGSTKFLT",
Signal::SIGCHLD => "SIGCHLD",
Signal::SIGCONT => "SIGCONT",
@@ -200,174 +244,125 @@ impl Signal {
Signal::SIGVTALRM => "SIGVTALRM",
Signal::SIGPROF => "SIGPROF",
Signal::SIGWINCH => "SIGWINCH",
+ #[cfg(not(target_os = "haiku"))]
Signal::SIGIO => "SIGIO",
- #[cfg(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux"))]
+ #[cfg(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux"
+ ))]
Signal::SIGPWR => "SIGPWR",
Signal::SIGSYS => "SIGSYS",
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux",
+ target_os = "redox",
+ target_os = "haiku"
+ )))]
Signal::SIGEMT => "SIGEMT",
- #[cfg(not(any(target_os = "android", target_os = "emscripten",
- target_os = "fuchsia", target_os = "linux",
- target_os = "redox")))]
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "linux",
+ target_os = "redox",
+ target_os = "haiku"
+ )))]
Signal::SIGINFO => "SIGINFO",
}
}
}
+#[cfg(feature = "signal")]
impl AsRef<str> for Signal {
fn as_ref(&self) -> &str {
self.as_str()
}
}
+#[cfg(feature = "signal")]
impl fmt::Display for Signal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.as_ref())
}
}
+#[cfg(feature = "signal")]
pub use self::Signal::*;
#[cfg(target_os = "redox")]
+#[cfg(feature = "signal")]
const SIGNALS: [Signal; 29] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGSYS];
-#[cfg(all(any(target_os = "linux", target_os = "android",
- target_os = "emscripten", target_os = "fuchsia"),
- not(any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64"))))]
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
+ SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
+ SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
+ SIGPROF, SIGWINCH, SIGIO, SIGSYS,
+];
+#[cfg(target_os = "haiku")]
+#[cfg(feature = "signal")]
+const SIGNALS: [Signal; 28] = [
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
+ SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
+ SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
+ SIGPROF, SIGWINCH, SIGSYS,
+];
+#[cfg(all(
+ any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia"
+ ),
+ not(any(
+ target_arch = "mips",
+ target_arch = "mips64",
+ target_arch = "sparc64"
+ ))
+))]
+#[cfg(feature = "signal")]
const SIGNALS: [Signal; 31] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGSTKFLT,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGPWR,
- SIGSYS];
-#[cfg(all(any(target_os = "linux", target_os = "android",
- target_os = "emscripten", target_os = "fuchsia"),
- any(target_arch = "mips", target_arch = "mips64",
- target_arch = "sparc64")))]
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
+ SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGSTKFLT, SIGCHLD,
+ SIGCONT, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ,
+ SIGVTALRM, SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
+];
+#[cfg(all(
+ any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "emscripten",
+ target_os = "fuchsia"
+ ),
+ any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")
+))]
+#[cfg(feature = "signal")]
const SIGNALS: [Signal; 30] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGPWR,
- SIGSYS];
-#[cfg(not(any(target_os = "linux", target_os = "android",
- target_os = "fuchsia", target_os = "emscripten",
- target_os = "redox")))]
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
+ SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
+ SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
+ SIGPROF, SIGWINCH, SIGIO, SIGPWR, SIGSYS,
+];
+#[cfg(not(any(
+ target_os = "linux",
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "emscripten",
+ target_os = "redox",
+ target_os = "haiku"
+)))]
+#[cfg(feature = "signal")]
const SIGNALS: [Signal; 31] = [
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGILL,
- SIGTRAP,
- SIGABRT,
- SIGBUS,
- SIGFPE,
- SIGKILL,
- SIGUSR1,
- SIGSEGV,
- SIGUSR2,
- SIGPIPE,
- SIGALRM,
- SIGTERM,
- SIGCHLD,
- SIGCONT,
- SIGSTOP,
- SIGTSTP,
- SIGTTIN,
- SIGTTOU,
- SIGURG,
- SIGXCPU,
- SIGXFSZ,
- SIGVTALRM,
- SIGPROF,
- SIGWINCH,
- SIGIO,
- SIGSYS,
- SIGEMT,
- SIGINFO];
+ SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGKILL,
+ SIGUSR1, SIGSEGV, SIGUSR2, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGCONT,
+ SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM,
+ SIGPROF, SIGWINCH, SIGIO, SIGSYS, SIGEMT, SIGINFO,
+];
+
+feature! {
+#![feature = "signal"]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
/// Iterate through all signals defined by this operating system
@@ -399,17 +394,26 @@ impl Signal {
/// Alias for [`SIGABRT`]
pub const SIGIOT : Signal = SIGABRT;
/// Alias for [`SIGIO`]
+#[cfg(not(target_os = "haiku"))]
pub const SIGPOLL : Signal = SIGIO;
/// Alias for [`SIGSYS`]
pub const SIGUNUSED : Signal = SIGSYS;
-#[cfg(not(target_os = "redox"))]
-type SaFlags_t = libc::c_int;
-#[cfg(target_os = "redox")]
-type SaFlags_t = libc::c_ulong;
+cfg_if! {
+ if #[cfg(target_os = "redox")] {
+ type SaFlags_t = libc::c_ulong;
+ } else if #[cfg(target_env = "uclibc")] {
+ type SaFlags_t = libc::c_ulong;
+ } else {
+ type SaFlags_t = libc::c_int;
+ }
+}
+}
-libc_bitflags!{
+#[cfg(feature = "signal")]
+libc_bitflags! {
/// Controls the behavior of a [`SigAction`]
+ #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
pub struct SaFlags: SaFlags_t {
/// When catching a [`Signal::SIGCHLD`] signal, the signal will be
/// generated only when a child process exits, not when a child process
@@ -435,10 +439,12 @@ libc_bitflags!{
}
}
+#[cfg(feature = "signal")]
libc_enum! {
/// Specifies how certain functions should manipulate a signal mask
#[repr(i32)]
#[non_exhaustive]
+ #[cfg_attr(docsrs, doc(cfg(feature = "signal")))]
pub enum SigmaskHow {
/// The new mask is the union of the current mask and the specified set.
SIG_BLOCK,
@@ -450,15 +456,26 @@ libc_enum! {
}
}
+feature! {
+#![feature = "signal"]
+
+use crate::unistd::Pid;
+use std::iter::Extend;
+use std::iter::FromIterator;
+use std::iter::IntoIterator;
+
/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
+// We are using `transparent` here to be super sure that `SigSet`
+// is represented exactly like the `sigset_t` struct from C.
+#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SigSet {
sigset: libc::sigset_t
}
-
impl SigSet {
/// Initialize to include all signals.
+ #[doc(alias("sigfillset"))]
pub fn all() -> SigSet {
let mut sigset = mem::MaybeUninit::uninit();
let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
@@ -467,6 +484,7 @@ impl SigSet {
}
/// Initialize to include nothing.
+ #[doc(alias("sigemptyset"))]
pub fn empty() -> SigSet {
let mut sigset = mem::MaybeUninit::uninit();
let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
@@ -475,21 +493,25 @@ impl SigSet {
}
/// Add the specified signal to the set.
+ #[doc(alias("sigaddset"))]
pub fn add(&mut self, signal: Signal) {
unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
/// Remove all signals from this set.
+ #[doc(alias("sigemptyset"))]
pub fn clear(&mut self) {
unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
}
/// Remove the specified signal from this set.
+ #[doc(alias("sigdelset"))]
pub fn remove(&mut self, signal: Signal) {
unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
/// Return whether this set includes the specified signal.
+ #[doc(alias("sigismember"))]
pub fn contains(&self, signal: Signal) -> bool {
let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
@@ -500,14 +522,9 @@ impl SigSet {
}
}
- /// Merge all of `other`'s signals into this set.
- // TODO: use libc::sigorset on supported operating systems.
- pub fn extend(&mut self, other: &SigSet) {
- for signal in Signal::iterator() {
- if other.contains(signal) {
- self.add(signal);
- }
- }
+ /// Returns an iterator that yields the signals contained in this set.
+ pub fn iter(&self) -> SigSetIter<'_> {
+ self.into_iter()
}
/// Gets the currently blocked (masked) set of signals for the calling thread.
@@ -542,6 +559,7 @@ impl SigSet {
/// Suspends execution of the calling thread until one of the signals in the
/// signal mask becomes pending, and returns the accepted signal.
#[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
+ #[cfg_attr(docsrs, doc(cfg(all())))]
pub fn wait(&self) -> Result<Signal> {
use std::convert::TryFrom;
@@ -552,6 +570,19 @@ impl SigSet {
Signal::try_from(signum.assume_init()).unwrap()
})
}
+
+ /// Converts a `libc::sigset_t` object to a [`SigSet`] without checking whether the
+ /// `libc::sigset_t` is already initialized.
+ ///
+ /// # Safety
+ ///
+ /// The `sigset` passed in must be a valid an initialized `libc::sigset_t` by calling either
+ /// [`sigemptyset(3)`](https://man7.org/linux/man-pages/man3/sigemptyset.3p.html) or
+ /// [`sigfillset(3)`](https://man7.org/linux/man-pages/man3/sigfillset.3p.html).
+ /// Otherwise, the results are undefined.
+ pub unsafe fn from_sigset_t_unchecked(sigset: libc::sigset_t) -> SigSet {
+ SigSet { sigset }
+ }
}
impl AsRef<libc::sigset_t> for SigSet {
@@ -560,6 +591,55 @@ impl AsRef<libc::sigset_t> for SigSet {
}
}
+// TODO: Consider specialization for the case where T is &SigSet and libc::sigorset is available.
+impl Extend<Signal> for SigSet {
+ fn extend<T>(&mut self, iter: T)
+ where T: IntoIterator<Item = Signal> {
+ for signal in iter {
+ self.add(signal);
+ }
+ }
+}
+
+impl FromIterator<Signal> for SigSet {
+ fn from_iter<T>(iter: T) -> Self
+ where T: IntoIterator<Item = Signal> {
+ let mut sigset = SigSet::empty();
+ sigset.extend(iter);
+ sigset
+ }
+}
+
+/// Iterator for a [`SigSet`].
+///
+/// Call [`SigSet::iter`] to create an iterator.
+#[derive(Clone, Debug)]
+pub struct SigSetIter<'a> {
+ sigset: &'a SigSet,
+ inner: SignalIterator,
+}
+
+impl Iterator for SigSetIter<'_> {
+ type Item = Signal;
+ fn next(&mut self) -> Option<Signal> {
+ loop {
+ match self.inner.next() {
+ None => return None,
+ Some(signal) if self.sigset.contains(signal) => return Some(signal),
+ Some(_signal) => continue,
+ }
+ }
+ }
+}
+
+impl<'a> IntoIterator for &'a SigSet {
+ type Item = Signal;
+ type IntoIter = SigSetIter<'a>;
+ fn into_iter(self) -> Self::IntoIter {
+ SigSetIter { sigset: self, inner: Signal::iterator() }
+ }
+}
+
/// A signal handler.
#[allow(unknown_lints)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -573,6 +653,7 @@ pub enum SigHandler {
/// Use the given signal-catching function, which takes in the signal, information about how
/// the signal was generated, and a pointer to the threads `ucontext_t`.
#[cfg(not(target_os = "redox"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
}
@@ -589,21 +670,12 @@ impl SigAction {
/// is the `SigAction` variant). `mask` specifies other signals to block during execution of
/// the signal-catching function.
pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
- #[cfg(target_os = "redox")]
- unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
- (*p).sa_handler = match handler {
- SigHandler::SigDfl => libc::SIG_DFL,
- SigHandler::SigIgn => libc::SIG_IGN,
- SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
- };
- }
-
- #[cfg(not(target_os = "redox"))]
unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
(*p).sa_sigaction = match handler {
SigHandler::SigDfl => libc::SIG_DFL,
SigHandler::SigIgn => libc::SIG_IGN,
SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
+ #[cfg(not(target_os = "redox"))]
SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
};
}
@@ -635,11 +707,11 @@ impl SigAction {
}
/// Returns the action's handler.
- #[cfg(not(target_os = "redox"))]
pub fn handler(&self) -> SigHandler {
match self.sigaction.sa_sigaction {
libc::SIG_DFL => SigHandler::SigDfl,
libc::SIG_IGN => SigHandler::SigIgn,
+ #[cfg(not(target_os = "redox"))]
p if self.flags().contains(SaFlags::SA_SIGINFO) =>
SigHandler::SigAction(
// Safe for one of two reasons:
@@ -667,27 +739,6 @@ impl SigAction {
as extern fn(libc::c_int)),
}
}
-
- /// Returns the action's handler.
- #[cfg(target_os = "redox")]
- pub fn handler(&self) -> SigHandler {
- match self.sigaction.sa_handler {
- libc::SIG_DFL => SigHandler::SigDfl,
- libc::SIG_IGN => SigHandler::SigIgn,
- p => SigHandler::Handler(
- // Safe for one of two reasons:
- // * The SigHandler was created by SigHandler::new, in which
- // case the pointer is correct, or
- // * The SigHandler was created by signal or sigaction, which
- // are unsafe functions, so the caller should've somehow
- // ensured that it is correctly initialized.
- unsafe{
- *(&p as *const usize
- as *const extern fn(libc::c_int))
- }
- as extern fn(libc::c_int)),
- }
- }
}
/// Changes the action taken by a process on receipt of a specific signal.
@@ -836,7 +887,7 @@ pub fn pthread_sigmask(how: SigmaskHow,
/// Examine and change blocked signals.
///
-/// For more informations see the [`sigprocmask` man
+/// For more information see the [`sigprocmask` man
/// pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
if set.is_none() && oldset.is_none() {
@@ -860,10 +911,11 @@ pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut Si
/// # Arguments
///
/// * `pid` - Specifies which processes should receive the signal.
-/// - If positive, specifies an individual process
+/// - If positive, specifies an individual process.
/// - If zero, the signal will be sent to all processes whose group
/// ID is equal to the process group ID of the sender. This is a
-/// variant of [`killpg`].
+#[cfg_attr(target_os = "fuchsia", doc = "variant of `killpg`.")]
+#[cfg_attr(not(target_os = "fuchsia"), doc = "variant of [`killpg`].")]
/// - If `-1` and the process has super-user privileges, the signal
/// is sent to all processes exclusing system processes.
/// - If less than `-1`, the signal is sent to all processes whose
@@ -912,7 +964,10 @@ pub fn raise(signal: Signal) -> Result<()> {
Errno::result(res).map(drop)
}
+}
+feature! {
+#![any(feature = "aio", feature = "signal")]
/// Identifies a thread for [`SigevNotify::SigevThreadId`]
#[cfg(target_os = "freebsd")]
@@ -942,6 +997,7 @@ pub enum SigevNotify {
// expose a way to set the union members needed by SIGEV_THREAD.
/// Notify by delivering an event to a kqueue.
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
SigevKevent {
/// File descriptor of the kqueue to notify.
kq: RawFd,
@@ -950,6 +1006,7 @@ pub enum SigevNotify {
},
/// Notify by delivering a signal to a thread.
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
+ #[cfg_attr(docsrs, doc(cfg(all())))]
SigevThreadId {
/// Signal to send
signal: Signal,
@@ -960,9 +1017,14 @@ pub enum SigevNotify {
si_value: libc::intptr_t
},
}
+}
#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
+#[cfg_attr(docsrs, doc(cfg(all())))]
mod sigevent {
+ feature! {
+ #![any(feature = "aio", feature = "signal")]
+
use std::mem;
use std::ptr;
use super::SigevNotify;
@@ -1005,6 +1067,8 @@ mod sigevent {
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
+ #[cfg(all(target_os = "linux", target_env = "uclibc"))]
+ SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
};
@@ -1044,6 +1108,11 @@ mod sigevent {
pub fn sigevent(&self) -> libc::sigevent {
self.sigevent
}
+
+ /// Returns a mutable pointer to the `sigevent` wrapped by `self`
+ pub fn as_mut_ptr(&mut self) -> *mut libc::sigevent {
+ &mut self.sigevent
+ }
}
impl<'a> From<&'a libc::sigevent> for SigEvent {
@@ -1051,13 +1120,14 @@ mod sigevent {
SigEvent{ sigevent: *sigevent }
}
}
+ }
}
#[cfg(test)]
mod tests {
+ use super::*;
#[cfg(not(target_os = "redox"))]
use std::thread;
- use super::*;
#[test]
fn test_contains() {
@@ -1120,15 +1190,19 @@ mod tests {
let mut test_mask = prev_mask;
test_mask.add(SIGUSR1);
- assert!(test_mask.thread_set_mask().is_ok());
- let new_mask = SigSet::thread_get_mask()
- .expect("Failed to get new mask!");
+ test_mask.thread_set_mask().expect("assertion failed");
+ let new_mask =
+ SigSet::thread_get_mask().expect("Failed to get new mask!");
assert!(new_mask.contains(SIGUSR1));
assert!(!new_mask.contains(SIGUSR2));
- prev_mask.thread_set_mask().expect("Failed to revert signal mask!");
- }).join().unwrap();
+ prev_mask
+ .thread_set_mask()
+ .expect("Failed to revert signal mask!");
+ })
+ .join()
+ .unwrap();
}
#[test]
@@ -1138,10 +1212,12 @@ mod tests {
let mut mask = SigSet::empty();
mask.add(SIGUSR1);
- assert!(mask.thread_block().is_ok());
+ mask.thread_block().expect("assertion failed");
assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- }).join().unwrap();
+ })
+ .join()
+ .unwrap();
}
#[test]
@@ -1151,10 +1227,12 @@ mod tests {
let mut mask = SigSet::empty();
mask.add(SIGUSR1);
- assert!(mask.thread_unblock().is_ok());
+ mask.thread_unblock().expect("assertion failed");
assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
- }).join().unwrap();
+ })
+ .join()
+ .unwrap();
}
#[test]
@@ -1170,36 +1248,51 @@ mod tests {
let mut mask2 = SigSet::empty();
mask2.add(SIGUSR2);
- let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK)
- .unwrap();
+ let oldmask =
+ mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK).unwrap();
assert!(oldmask.contains(SIGUSR1));
assert!(!oldmask.contains(SIGUSR2));
assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
- }).join().unwrap();
+ })
+ .join()
+ .unwrap();
+ }
+
+ #[test]
+ fn test_from_and_into_iterator() {
+ let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
+ let signals = sigset.into_iter().collect::<Vec<Signal>>();
+ assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
}
#[test]
#[cfg(not(target_os = "redox"))]
fn test_sigaction() {
thread::spawn(|| {
- extern fn test_sigaction_handler(_: libc::c_int) {}
- extern fn test_sigaction_action(_: libc::c_int,
- _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
+ extern "C" fn test_sigaction_handler(_: libc::c_int) {}
+ extern "C" fn test_sigaction_action(
+ _: libc::c_int,
+ _: *mut libc::siginfo_t,
+ _: *mut libc::c_void,
+ ) {
+ }
let handler_sig = SigHandler::Handler(test_sigaction_handler);
- let flags = SaFlags::SA_ONSTACK | SaFlags::SA_RESTART |
- SaFlags::SA_SIGINFO;
+ let flags =
+ SaFlags::SA_ONSTACK | SaFlags::SA_RESTART | SaFlags::SA_SIGINFO;
let mut mask = SigSet::empty();
mask.add(SIGUSR1);
let action_sig = SigAction::new(handler_sig, flags, mask);
- assert_eq!(action_sig.flags(),
- SaFlags::SA_ONSTACK | SaFlags::SA_RESTART);
+ assert_eq!(
+ action_sig.flags(),
+ SaFlags::SA_ONSTACK | SaFlags::SA_RESTART
+ );
assert_eq!(action_sig.handler(), handler_sig);
mask = action_sig.mask();
@@ -1215,7 +1308,9 @@ mod tests {
let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
assert_eq!(action_ign.handler(), SigHandler::SigIgn);
- }).join().unwrap();
+ })
+ .join()
+ .unwrap();
}
#[test]
@@ -1229,6 +1324,25 @@ mod tests {
raise(SIGUSR1).unwrap();
assert_eq!(mask.wait().unwrap(), SIGUSR1);
- }).join().unwrap();
+ })
+ .join()
+ .unwrap();
+ }
+
+ #[test]
+ fn test_from_sigset_t_unchecked() {
+ let src_set = SigSet::empty();
+ let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
+
+ for signal in Signal::iterator() {
+ assert!(!set.contains(signal));
+ }
+
+ let src_set = SigSet::all();
+ let set = unsafe { SigSet::from_sigset_t_unchecked(src_set.sigset) };
+
+ for signal in Signal::iterator() {
+ assert!(set.contains(signal));
+ }
}
}