summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Matthias Schaefer <philipp.matthias.schaefer@posteo.de>2016-04-25 13:03:05 +0200
committerPhilipp Matthias Schaefer <philipp.matthias.schaefer@posteo.de>2016-06-26 15:04:15 +0200
commit5c7b3c14953881eec113513e1a4881daf960a98c (patch)
tree02d35894b0e03b1c9f0097cd7cd96053e3121d7e
parentd9f63166dee3bd362af9dc929773d6ae810541f2 (diff)
downloadnix-5c7b3c14953881eec113513e1a4881daf960a98c.zip
Convert signal constants to enumeration.
-rw-r--r--src/sys/signal.rs249
-rw-r--r--src/sys/wait.rs40
2 files changed, 194 insertions, 95 deletions
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index a881a51e..2214d4b9 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -2,11 +2,60 @@
// See http://rust-lang.org/COPYRIGHT.
use libc;
-use {Errno, Result};
+use {Errno, Error, Result};
use std::mem;
use std::ptr;
-pub use libc::{
+// Currently there is only one definition of c_int in libc, as well as only one
+// type for signal constants.
+// We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
+// this is not (yet) possible.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[repr(i32)]
+pub enum Signal {
+ SIGHUP = libc::SIGHUP,
+ SIGINT = libc::SIGINT,
+ SIGQUIT = libc::SIGQUIT,
+ SIGILL = libc::SIGILL,
+ SIGTRAP = libc::SIGTRAP,
+ SIGABRT = libc::SIGABRT,
+ SIGBUS = libc::SIGBUS,
+ SIGFPE = libc::SIGFPE,
+ SIGKILL = libc::SIGKILL,
+ SIGUSR1 = libc::SIGUSR1,
+ SIGSEGV = libc::SIGSEGV,
+ SIGUSR2 = libc::SIGUSR2,
+ SIGPIPE = libc::SIGPIPE,
+ SIGALRM = libc::SIGALRM,
+ SIGTERM = libc::SIGTERM,
+ #[cfg(not(target_os = "macos"))]
+ SIGSTKFLT = libc::SIGSTKFLT,
+ SIGCHLD = libc::SIGCHLD,
+ SIGCONT = libc::SIGCONT,
+ SIGSTOP = libc::SIGSTOP,
+ SIGTSTP = libc::SIGTSTP,
+ SIGTTIN = libc::SIGTTIN,
+ SIGTTOU = libc::SIGTTOU,
+ SIGURG = libc::SIGURG,
+ SIGXCPU = libc::SIGXCPU,
+ SIGXFSZ = libc::SIGXFSZ,
+ SIGVTALRM = libc::SIGVTALRM,
+ SIGPROF = libc::SIGPROF,
+ SIGWINCH = libc::SIGWINCH,
+ SIGIO = libc::SIGIO,
+ #[cfg(not(target_os = "macos"))]
+ SIGPWR = libc::SIGPWR,
+ SIGSYS = libc::SIGSYS,
+ #[cfg(target_os = "macos")]
+ SIGEMT = libc::SIGEMT,
+ #[cfg(target_os = "macos")]
+ SIGINFO = libc::SIGINFO,
+}
+
+pub use self::Signal::*;
+
+#[cfg(not(target_os = "macos"))]
+const SIGNALS: [Signal; 31] = [
SIGHUP,
SIGINT,
SIGQUIT,
@@ -22,6 +71,7 @@ pub use libc::{
SIGPIPE,
SIGALRM,
SIGTERM,
+ SIGSTKFLT,
SIGCHLD,
SIGCONT,
SIGSTOP,
@@ -35,26 +85,83 @@ pub use libc::{
SIGPROF,
SIGWINCH,
SIGIO,
- SIGSYS,
-};
-
+ SIGPWR,
+ SIGSYS];
#[cfg(target_os = "macos")]
-pub use libc::{
+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,
-};
-
-#[cfg(not(target_os = "macos"))]
-pub use libc::{
- SIGPWR,
- SIGSTKFLT,
- SIGIOT, // Alias for SIGABRT
- SIGPOLL, // Alias for SIGIO
- SIGUNUSED, // Alias for 31
-};
+ SIGINFO];
pub const NSIG: libc::c_int = 32;
+pub struct SignalIterator {
+ next: usize,
+}
+
+impl Iterator for SignalIterator {
+ type Item = Signal;
+
+ fn next(&mut self) -> Option<Signal> {
+ if self.next < SIGNALS.len() {
+ let next_signal = SIGNALS[self.next];
+ self.next += 1;
+ Some(next_signal)
+ } else {
+ None
+ }
+ }
+}
+
+impl Signal {
+ pub fn iterator() -> SignalIterator {
+ SignalIterator{next: 0}
+ }
+
+ // We do not implement the From trait, because it is supposed to be infallible.
+ // With Rust RFC 1542 comes the appropriate trait TryFrom. Once it is
+ // implemented, we'll replace this function.
+ #[inline]
+ pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
+ match 0 < signum && signum < NSIG {
+ true => Ok(unsafe { mem::transmute(signum) }),
+ false => Err(Error::invalid_argument()),
+ }
+ }
+}
+
+pub const SIGIOT : Signal = SIGABRT;
+pub const SIGPOLL : Signal = SIGIO;
+pub const SIGUNUSED : Signal = SIGSYS;
+
bitflags!{
flags SaFlags: libc::c_int {
const SA_NOCLDSTOP = libc::SA_NOCLDSTOP,
@@ -80,7 +187,6 @@ pub struct SigSet {
sigset: libc::sigset_t
}
-pub type SigNum = libc::c_int;
impl SigSet {
pub fn all() -> SigSet {
@@ -97,40 +203,33 @@ impl SigSet {
SigSet { sigset: sigset }
}
- pub fn add(&mut self, signum: SigNum) -> Result<()> {
- let res = unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signum) };
-
- Errno::result(res).map(drop)
+ pub fn add(&mut self, signal: Signal) {
+ unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
- pub fn clear(&mut self) -> Result<()> {
- let res = unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
-
- Errno::result(res).map(drop)
+ pub fn clear(&mut self) {
+ unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
}
- pub fn remove(&mut self, signum: SigNum) -> Result<()> {
- let res = unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signum) };
-
- Errno::result(res).map(drop)
+ pub fn remove(&mut self, signal: Signal) {
+ unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
}
- pub fn extend(&mut self, other: &SigSet) -> Result<()> {
- for i in 1..NSIG {
- if try!(other.contains(i)) {
- try!(self.add(i));
- }
+ pub fn contains(&self, signal: Signal) -> bool {
+ let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
+
+ match res {
+ 1 => true,
+ 0 => false,
+ _ => unreachable!("unexpected value from sigismember"),
}
- Ok(())
}
- pub fn contains(&self, signum: SigNum) -> Result<bool> {
- let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signum) };
-
- match try!(Errno::result(res)) {
- 1 => Ok(true),
- 0 => Ok(false),
- _ => unreachable!("unexpected value from sigismember"),
+ pub fn extend(&mut self, other: &SigSet) {
+ for signal in Signal::iterator() {
+ if other.contains(signal) {
+ self.add(signal);
+ }
}
}
@@ -165,11 +264,11 @@ impl SigSet {
/// Suspends execution of the calling thread until one of the signals in the
/// signal mask becomes pending, and returns the accepted signal.
- pub fn wait(&self) -> Result<SigNum> {
- let mut signum: SigNum = unsafe { mem::uninitialized() };
+ pub fn wait(&self) -> Result<Signal> {
+ let mut signum: libc::c_int = unsafe { mem::uninitialized() };
let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
- Errno::result(res).map(|_| signum)
+ Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
}
}
@@ -185,8 +284,8 @@ impl AsRef<libc::sigset_t> for SigSet {
pub enum SigHandler {
SigDfl,
SigIgn,
- Handler(extern fn(SigNum)),
- SigAction(extern fn(SigNum, *mut libc::siginfo_t, *mut libc::c_void))
+ Handler(extern fn(libc::c_int)),
+ SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
}
pub struct SigAction {
@@ -214,11 +313,11 @@ impl SigAction {
}
}
-pub unsafe fn sigaction(signum: SigNum, sigaction: &SigAction) -> Result<SigAction> {
+pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
let mut oldact = mem::uninitialized::<libc::sigaction>();
let res =
- libc::sigaction(signum, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
+ libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
Errno::result(res).map(|_| SigAction { sigaction: oldact })
}
@@ -257,14 +356,14 @@ pub fn pthread_sigmask(how: SigFlags,
Errno::result(res).map(drop)
}
-pub fn kill(pid: libc::pid_t, signum: SigNum) -> Result<()> {
- let res = unsafe { libc::kill(pid, signum) };
+pub fn kill(pid: libc::pid_t, signal: Signal) -> Result<()> {
+ let res = unsafe { libc::kill(pid, signal as libc::c_int) };
Errno::result(res).map(drop)
}
-pub fn raise(signum: SigNum) -> Result<()> {
- let res = unsafe { libc::raise(signum) };
+pub fn raise(signal: Signal) -> Result<()> {
+ let res = unsafe { libc::raise(signal as libc::c_int) };
Errno::result(res).map(drop)
}
@@ -276,42 +375,42 @@ mod tests {
#[test]
fn test_contains() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
+ mask.add(SIGUSR1);
- assert_eq!(mask.contains(SIGUSR1), Ok(true));
- assert_eq!(mask.contains(SIGUSR2), Ok(false));
+ assert!(mask.contains(SIGUSR1));
+ assert!(!mask.contains(SIGUSR2));
let all = SigSet::all();
- assert_eq!(all.contains(SIGUSR1), Ok(true));
- assert_eq!(all.contains(SIGUSR2), Ok(true));
+ assert!(all.contains(SIGUSR1));
+ assert!(all.contains(SIGUSR2));
}
#[test]
fn test_clear() {
let mut set = SigSet::all();
- set.clear().unwrap();
- for i in 1..NSIG {
- assert_eq!(set.contains(i), Ok(false));
+ set.clear();
+ for signal in Signal::iterator() {
+ assert!(!set.contains(signal));
}
}
#[test]
fn test_extend() {
let mut one_signal = SigSet::empty();
- one_signal.add(SIGUSR1).unwrap();
+ one_signal.add(SIGUSR1);
let mut two_signals = SigSet::empty();
- two_signals.add(SIGUSR2).unwrap();
- two_signals.extend(&one_signal).unwrap();
+ two_signals.add(SIGUSR2);
+ two_signals.extend(&one_signal);
- assert_eq!(two_signals.contains(SIGUSR1), Ok(true));
- assert_eq!(two_signals.contains(SIGUSR2), Ok(true));
+ assert!(two_signals.contains(SIGUSR1));
+ assert!(two_signals.contains(SIGUSR2));
}
#[test]
fn test_thread_signal_block() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
+ mask.add(SIGUSR1);
assert!(mask.thread_block().is_ok());
}
@@ -319,18 +418,18 @@ mod tests {
#[test]
fn test_thread_signal_swap() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
+ mask.add(SIGUSR1);
mask.thread_block().unwrap();
- assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1).unwrap());
+ assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
let mask2 = SigSet::empty();
- mask.add(SIGUSR2).unwrap();
+ mask.add(SIGUSR2);
let oldmask = mask2.thread_swap_mask(SIG_SETMASK).unwrap();
- assert!(oldmask.contains(SIGUSR1).unwrap());
- assert!(!oldmask.contains(SIGUSR2).unwrap());
+ assert!(oldmask.contains(SIGUSR1));
+ assert!(!oldmask.contains(SIGUSR2));
}
// TODO(#251): Re-enable after figuring out flakiness.
@@ -338,8 +437,8 @@ mod tests {
#[test]
fn test_sigwait() {
let mut mask = SigSet::empty();
- mask.add(SIGUSR1).unwrap();
- mask.add(SIGUSR2).unwrap();
+ mask.add(SIGUSR1);
+ mask.add(SIGUSR2);
mask.thread_block().unwrap();
raise(SIGUSR1).unwrap();
diff --git a/src/sys/wait.rs b/src/sys/wait.rs
index 3d9b3a50..80a8acaa 100644
--- a/src/sys/wait.rs
+++ b/src/sys/wait.rs
@@ -1,7 +1,7 @@
use libc::{pid_t, c_int};
use {Errno, Result};
-use sys::signal;
+use sys::signal::Signal;
mod ffi {
use libc::{pid_t, c_int};
@@ -41,8 +41,8 @@ const WSTOPPED: WaitPidFlag = WUNTRACED;
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum WaitStatus {
Exited(pid_t, i8),
- Signaled(pid_t, signal::SigNum, bool),
- Stopped(pid_t, signal::SigNum),
+ Signaled(pid_t, Signal, bool),
+ Stopped(pid_t, Signal),
Continued(pid_t),
StillAlive
}
@@ -50,7 +50,7 @@ pub enum WaitStatus {
#[cfg(any(target_os = "linux",
target_os = "android"))]
mod status {
- use sys::signal;
+ use sys::signal::Signal;
pub fn exited(status: i32) -> bool {
(status & 0x7F) == 0
@@ -64,8 +64,8 @@ mod status {
((((status & 0x7f) + 1) as i8) >> 1) > 0
}
- pub fn term_signal(status: i32) -> signal::SigNum {
- (status & 0x7f) as signal::SigNum
+ pub fn term_signal(status: i32) -> Signal {
+ Signal::from_c_int(status & 0x7f).unwrap()
}
pub fn dumped_core(status: i32) -> bool {
@@ -76,8 +76,8 @@ mod status {
(status & 0xff) == 0x7f
}
- pub fn stop_signal(status: i32) -> signal::SigNum {
- ((status & 0xFF00) >> 8) as signal::SigNum
+ pub fn stop_signal(status: i32) -> Signal {
+ Signal::from_c_int((status & 0xFF00) >> 8).unwrap()
}
pub fn continued(status: i32) -> bool {
@@ -88,7 +88,7 @@ mod status {
#[cfg(any(target_os = "macos",
target_os = "ios"))]
mod status {
- use sys::signal;
+ use sys::signal::{Signal,SIGCONT};
const WCOREFLAG: i32 = 0x80;
const WSTOPPED: i32 = 0x7f;
@@ -101,16 +101,16 @@ mod status {
((status >> 8) & 0xFF) as i8
}
- pub fn stop_signal(status: i32) -> signal::SigNum {
- (status >> 8) as signal::SigNum
+ pub fn stop_signal(status: i32) -> Signal {
+ Signal::from_c_int(status >> 8).unwrap()
}
pub fn continued(status: i32) -> bool {
- wstatus(status) == WSTOPPED && stop_signal(status) == 0x13
+ wstatus(status) == WSTOPPED && stop_signal(status) == SIGCONT
}
pub fn stopped(status: i32) -> bool {
- wstatus(status) == WSTOPPED && stop_signal(status) != 0x13
+ wstatus(status) == WSTOPPED && stop_signal(status) != SIGCONT
}
pub fn exited(status: i32) -> bool {
@@ -121,8 +121,8 @@ mod status {
wstatus(status) != WSTOPPED && wstatus(status) != 0
}
- pub fn term_signal(status: i32) -> signal::SigNum {
- wstatus(status) as signal::SigNum
+ pub fn term_signal(status: i32) -> Signal {
+ Signal::from_c_int(wstatus(status)).unwrap()
}
pub fn dumped_core(status: i32) -> bool {
@@ -135,7 +135,7 @@ mod status {
target_os = "dragonfly",
target_os = "netbsd"))]
mod status {
- use sys::signal;
+ use sys::signal::Signal;
const WCOREFLAG: i32 = 0x80;
const WSTOPPED: i32 = 0x7f;
@@ -148,16 +148,16 @@ mod status {
wstatus(status) == WSTOPPED
}
- pub fn stop_signal(status: i32) -> signal::SigNum {
- (status >> 8) as signal::SigNum
+ pub fn stop_signal(status: i32) -> Signal {
+ Signal::from_c_int(status >> 8).unwrap()
}
pub fn signaled(status: i32) -> bool {
wstatus(status) != WSTOPPED && wstatus(status) != 0 && status != 0x13
}
- pub fn term_signal(status: i32) -> signal::SigNum {
- wstatus(status) as signal::SigNum
+ pub fn term_signal(status: i32) -> Signal {
+ Signal::from_c_int(wstatus(status)).unwrap()
}
pub fn exited(status: i32) -> bool {