summaryrefslogtreecommitdiff
path: root/src/sys/signal.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sys/signal.rs')
-rw-r--r--src/sys/signal.rs354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
new file mode 100644
index 00000000..d8d7c088
--- /dev/null
+++ b/src/sys/signal.rs
@@ -0,0 +1,354 @@
+// Portions of this file are Copyright 2014 The Rust Project Developers.
+// See http://rust-lang.org/COPYRIGHT.
+
+use libc;
+use core::mem;
+use errno::{SysError, SysResult};
+
+pub use libc::consts::os::posix88::{
+ SIGHUP, // 1
+ SIGINT, // 2
+ SIGQUIT, // 3
+ SIGILL, // 4
+ SIGABRT, // 6
+ SIGFPE, // 8
+ SIGKILL, // 9
+ SIGSEGV, // 11
+ SIGPIPE, // 13
+ SIGALRM, // 14
+ SIGTERM, // 15
+};
+
+pub use self::signal::{
+ SIGTRAP,
+ SIGIOT,
+ SIGBUS,
+ SIGSYS,
+ SIGURG,
+ SIGSTOP,
+ SIGTSTP,
+ SIGCONT,
+ SIGCHLD,
+ SIGTTIN,
+ SIGTTOU,
+ SIGIO,
+ SIGXCPU,
+ SIGXFSZ,
+ SIGVTALRM,
+ SIGPROF,
+ SIGWINCH,
+ SIGUSR1,
+ SIGUSR2,
+};
+
+pub use self::signal::SockFlag;
+pub use self::signal::sigset_t;
+
+// This doesn't always exist, but when it does, it's 7
+pub const SIGEMT: libc::c_int = 7;
+
+#[cfg(any(all(target_os = "linux",
+ any(target_arch = "x86",
+ target_arch = "x86_64",
+ target_arch = "arm")),
+ target_os = "android"))]
+pub mod signal {
+ use libc;
+
+ bitflags!(
+ flags SockFlag: libc::c_ulong {
+ const SA_NOCLDSTOP = 0x00000001,
+ const SA_NOCLDWAIT = 0x00000002,
+ const SA_NODEFER = 0x40000000,
+ const SA_ONSTACK = 0x08000000,
+ const SA_RESETHAND = 0x80000000,
+ const SA_RESTART = 0x10000000,
+ const SA_SIGINFO = 0x00000004,
+ }
+ )
+
+ pub const SIGTRAP: libc::c_int = 5;
+ pub const SIGIOT: libc::c_int = 6;
+ pub const SIGBUS: libc::c_int = 7;
+ pub const SIGUSR1: libc::c_int = 10;
+ pub const SIGUSR2: libc::c_int = 12;
+ pub const SIGSTKFLT: libc::c_int = 16;
+ pub const SIGCHLD: libc::c_int = 17;
+ pub const SIGCONT: libc::c_int = 18;
+ pub const SIGSTOP: libc::c_int = 19;
+ pub const SIGTSTP: libc::c_int = 20;
+ pub const SIGTTIN: libc::c_int = 21;
+ pub const SIGTTOU: libc::c_int = 22;
+ pub const SIGURG: libc::c_int = 23;
+ pub const SIGXCPU: libc::c_int = 24;
+ pub const SIGXFSZ: libc::c_int = 25;
+ pub const SIGVTALRM: libc::c_int = 26;
+ pub const SIGPROF: libc::c_int = 27;
+ pub const SIGWINCH: libc::c_int = 28;
+ pub const SIGIO: libc::c_int = 29;
+ pub const SIGPOLL: libc::c_int = 29;
+ pub const SIGPWR: libc::c_int = 30;
+ pub const SIGSYS: libc::c_int = 31;
+ pub const SIGUNUSED: libc::c_int = 31;
+
+ // This definition is not as accurate as it could be, {pid, uid, status} is
+ // actually a giant union. Currently we're only interested in these fields,
+ // however.
+ #[repr(C)]
+ pub struct siginfo {
+ si_signo: libc::c_int,
+ si_errno: libc::c_int,
+ si_code: libc::c_int,
+ pub pid: libc::pid_t,
+ pub uid: libc::uid_t,
+ pub status: libc::c_int,
+ }
+
+ #[repr(C)]
+ pub struct sigaction {
+ pub sa_handler: extern fn(libc::c_int),
+ pub sa_mask: sigset_t,
+ pub sa_flags: SockFlag,
+ sa_restorer: *mut libc::c_void,
+ }
+
+ #[repr(C)]
+ #[cfg(target_word_size = "32")]
+ pub struct sigset_t {
+ __val: [libc::c_ulong, ..32],
+ }
+
+ #[repr(C)]
+ #[cfg(target_word_size = "64")]
+ pub struct sigset_t {
+ __val: [libc::c_ulong, ..16],
+ }
+}
+
+#[cfg(all(target_os = "linux",
+ any(target_arch = "mips", target_arch = "mipsel")))]
+pub mod signal {
+ use libc;
+
+ bitflags!(
+ flags SockFlag: libc::c_uint {
+ const SA_NOCLDSTOP = 0x00000001,
+ const SA_NOCLDWAIT = 0x00001000,
+ const SA_NODEFER = 0x40000000,
+ const SA_ONSTACK = 0x08000000,
+ const SA_RESETHAND = 0x80000000,
+ const SA_RESTART = 0x10000000,
+ const SA_SIGINFO = 0x00000008,
+ }
+ )
+
+ pub const SIGTRAP: libc::c_int = 5;
+ pub const SIGIOT: libc::c_int = 6;
+ pub const SIGBUS: libc::c_int = 10;
+ pub const SIGSYS: libc::c_int = 12;
+ pub const SIGUSR1: libc::c_int = 16;
+ pub const SIGUSR2: libc::c_int = 17;
+ pub const SIGCHLD: libc::c_int = 18;
+ pub const SIGCLD: libc::c_int = 18;
+ pub const SIGPWR: libc::c_int = 19;
+ pub const SIGWINCH: libc::c_int = 20;
+ pub const SIGURG: libc::c_int = 21;
+ pub const SIGIO: libc::c_int = 22;
+ pub const SIGPOLL: libc::c_int = 22;
+ pub const SIGSTOP: libc::c_int = 23;
+ pub const SIGTSTP: libc::c_int = 24;
+ pub const SIGCONT: libc::c_int = 25;
+ pub const SIGTTIN: libc::c_int = 26;
+ pub const SIGTTOU: libc::c_int = 27;
+ pub const SIGVTALRM: libc::c_int = 28;
+ pub const SIGPROF: libc::c_int = 29;
+ pub const SIGXCPU: libc::c_int = 30;
+ pub const SIGFSZ: libc::c_int = 31;
+
+ // This definition is not as accurate as it could be, {pid, uid, status} is
+ // actually a giant union. Currently we're only interested in these fields,
+ // however.
+ #[repr(C)]
+ pub struct siginfo {
+ si_signo: libc::c_int,
+ si_code: libc::c_int,
+ si_errno: libc::c_int,
+ pub pid: libc::pid_t,
+ pub uid: libc::uid_t,
+ pub status: libc::c_int,
+ }
+
+ #[repr(C)]
+ pub struct sigaction {
+ pub sa_flags: SockFlag,
+ pub sa_handler: extern fn(libc::c_int),
+ pub sa_mask: sigset_t,
+ sa_restorer: *mut libc::c_void,
+ sa_resv: [libc::c_int, ..1],
+ }
+
+ #[repr(C)]
+ pub struct sigset_t {
+ __val: [libc::c_ulong, ..32],
+ }
+}
+
+#[cfg(any(target_os = "macos",
+ target_os = "ios",
+ target_os = "freebsd",
+ target_os = "dragonfly"))]
+pub mod signal {
+ use libc;
+
+ bitflags!(
+ flags SockFlag: libc::c_int {
+ const SA_NOCLDSTOP = 0x0008,
+ const SA_NOCLDWAIT = 0x0020,
+ const SA_NODEFER = 0x0010,
+ const SA_ONSTACK = 0x0001,
+ const SA_RESETHAND = 0x0004,
+ const SA_RESTART = 0x0002,
+ const SA_SIGINFO = 0x0040,
+ }
+ )
+
+ pub const SIGTRAP: libc::c_int = 5;
+ pub const SIGIOT: libc::c_int = 6;
+ pub const SIGBUS: libc::c_int = 10;
+ pub const SIGSYS: libc::c_int = 12;
+ pub const SIGURG: libc::c_int = 16;
+ pub const SIGSTOP: libc::c_int = 17;
+ pub const SIGTSTP: libc::c_int = 18;
+ pub const SIGCONT: libc::c_int = 19;
+ pub const SIGCHLD: libc::c_int = 20;
+ pub const SIGTTIN: libc::c_int = 21;
+ pub const SIGTTOU: libc::c_int = 22;
+ pub const SIGIO: libc::c_int = 23;
+ pub const SIGXCPU: libc::c_int = 24;
+ pub const SIGXFSZ: libc::c_int = 25;
+ pub const SIGVTALRM: libc::c_int = 26;
+ pub const SIGPROF: libc::c_int = 27;
+ pub const SIGWINCH: libc::c_int = 28;
+ pub const SIGINFO: libc::c_int = 29;
+ pub const SIGUSR1: libc::c_int = 30;
+ pub const SIGUSR2: libc::c_int = 31;
+
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ pub type sigset_t = u32;
+ #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[repr(C)]
+ pub struct sigset_t {
+ bits: [u32, ..4],
+ }
+
+ // This structure has more fields, but we're not all that interested in
+ // them.
+ #[repr(C)]
+ pub struct siginfo {
+ pub si_signo: libc::c_int,
+ pub si_errno: libc::c_int,
+ pub si_code: libc::c_int,
+ pub pid: libc::pid_t,
+ pub uid: libc::uid_t,
+ pub status: libc::c_int,
+ }
+
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ #[repr(C)]
+ pub struct sigaction {
+ pub sa_handler: extern fn(libc::c_int),
+ sa_tramp: *mut libc::c_void,
+ pub sa_mask: sigset_t,
+ pub sa_flags: SockFlag,
+ }
+
+ #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+ #[repr(C)]
+ pub struct sigaction {
+ pub sa_handler: extern fn(libc::c_int),
+ pub sa_flags: SockFlag,
+ pub sa_mask: sigset_t,
+ }
+
+}
+
+mod ffi {
+ use libc;
+ use super::signal::{sigaction, sigset_t};
+
+ extern {
+ pub fn sigaction(signum: libc::c_int,
+ act: *const sigaction,
+ oldact: *mut sigaction) -> libc::c_int;
+
+ pub fn sigaddset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
+ pub fn sigdelset(set: *mut sigset_t, signum: libc::c_int) -> libc::c_int;
+ pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
+ }
+}
+
+pub struct SigSet {
+ sigset: sigset_t
+}
+
+pub type SigNum = libc::c_int;
+
+impl SigSet {
+ pub fn empty() -> SigSet {
+ let mut sigset = unsafe { mem::uninitialized::<sigset_t>() };
+ let _ = unsafe { ffi::sigemptyset(&mut sigset as *mut sigset_t) };
+
+ SigSet { sigset: sigset }
+ }
+
+ pub fn add(&mut self, signum: SigNum) -> SysResult<()> {
+ let res = unsafe { ffi::sigaddset(&mut self.sigset as *mut sigset_t, signum) };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ Ok(())
+ }
+
+ pub fn remove(&mut self, signum: SigNum) -> SysResult<()> {
+ let res = unsafe { ffi::sigdelset(&mut self.sigset as *mut sigset_t, signum) };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ Ok(())
+ }
+}
+
+type sigaction_t = self::signal::sigaction;
+
+pub struct SigAction {
+ sigaction: sigaction_t
+}
+
+impl SigAction {
+ pub fn new(handler: extern fn(libc::c_int), flags: SockFlag, mask: SigSet) -> SigAction {
+ let mut s = unsafe { mem::uninitialized::<sigaction_t>() };
+ s.sa_handler = handler;
+ s.sa_flags = flags;
+ s.sa_mask = mask.sigset;
+
+ SigAction { sigaction: s }
+ }
+}
+
+pub fn sigaction(signum: SigNum, sigaction: &SigAction) -> SysResult<SigAction> {
+ let mut oldact = unsafe { mem::uninitialized::<sigaction_t>() };
+
+ let res = unsafe {
+ ffi::sigaction(signum, &sigaction.sigaction as *const sigaction_t, &mut oldact as *mut sigaction_t)
+ };
+
+ if res < 0 {
+ return Err(SysError::last());
+ }
+
+ Ok(SigAction { sigaction: oldact })
+}