about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/process.rs18
-rw-r--r--src/libstd/sys/unix/c.rs421
-rw-r--r--src/libstd/sys/unix/process.rs84
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs141
5 files changed, 305 insertions, 361 deletions
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index e5242c5bf86..e27e4ba5af2 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -148,8 +148,6 @@
 #![feature(vec_push_all)]
 #![feature(wrapping)]
 #![feature(zero_one)]
-#![cfg_attr(all(unix, not(target_os = "macos"), not(target_os = "ios")),
-            feature(num_bits_bytes))]
 #![cfg_attr(windows, feature(str_utf16))]
 #![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras))]
 #![cfg_attr(test, feature(test, rustc_private, float_consts))]
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index d70b9f09903..a8127b3200f 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -770,24 +770,6 @@ mod tests {
     }
 
     #[cfg(all(unix, not(target_os="android")))]
-    pub fn pwd_cmd() -> Command {
-        Command::new("pwd")
-    }
-    #[cfg(target_os="android")]
-    pub fn pwd_cmd() -> Command {
-        let mut cmd = Command::new("/system/bin/sh");
-        cmd.arg("-c").arg("pwd");
-        cmd
-    }
-
-    #[cfg(windows)]
-    pub fn pwd_cmd() -> Command {
-        let mut cmd = Command::new("cmd");
-        cmd.arg("/c").arg("cd");
-        cmd
-    }
-
-    #[cfg(all(unix, not(target_os="android")))]
     pub fn env_cmd() -> Command {
         Command::new("env")
     }
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index 1e68eac5a67..99a6731c57d 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -8,15 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! C definitions used by libnative that don't belong in liblibc
+//! C definitions used by std::sys that don't belong in liblibc
+
+// These are definitions sufficient for the users in this directory.
+// This is not a general-purpose binding to this functionality, and in
+// some cases (notably the definition of siginfo_t), we intentionally
+// have incomplete bindings so that we don't need to fight with unions.
+//
+// Note that these types need to match the definitions from the platform
+// libc (currently glibc on Linux), not the kernel definitions / the
+// syscall interface.  This has a few weirdnesses, like glibc's sigset_t
+// being 1024 bits on all platforms. If you're adding a new GNU/Linux
+// port, check glibc's sysdeps/unix/sysv/linux, not the kernel headers.
 
 #![allow(dead_code)]
 #![allow(non_camel_case_types)]
 
-pub use self::select::fd_set;
-pub use self::signal::{sigaction, siginfo, sigset_t};
-pub use self::signal::{SA_ONSTACK, SA_RESTART, SA_RESETHAND, SA_NOCLDSTOP};
-pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD};
+pub use self::signal_os::{sigaction, siginfo, sigset_t, sigaltstack};
+pub use self::signal_os::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIGSTKSZ, SIG_SETMASK};
 
 use libc;
 
@@ -26,45 +35,21 @@ use libc;
           target_os = "dragonfly",
           target_os = "bitrig",
           target_os = "openbsd"))]
-mod consts {
-    use libc;
-    pub const FIONBIO: libc::c_ulong = 0x8004667e;
-    pub const FIOCLEX: libc::c_ulong = 0x20006601;
-    pub const FIONCLEX: libc::c_ulong = 0x20006602;
-}
+pub const FIOCLEX: libc::c_ulong = 0x20006601;
+
 #[cfg(any(all(target_os = "linux",
               any(target_arch = "x86",
                   target_arch = "x86_64",
                   target_arch = "arm",
                   target_arch = "aarch64")),
           target_os = "android"))]
-mod consts {
-    use libc;
-    pub const FIONBIO: libc::c_ulong = 0x5421;
-    pub const FIOCLEX: libc::c_ulong = 0x5451;
-    pub const FIONCLEX: libc::c_ulong = 0x5450;
-}
+pub const FIOCLEX: libc::c_ulong = 0x5451;
+
 #[cfg(all(target_os = "linux",
           any(target_arch = "mips",
               target_arch = "mipsel",
               target_arch = "powerpc")))]
-mod consts {
-    use libc;
-    pub const FIONBIO: libc::c_ulong = 0x667e;
-    pub const FIOCLEX: libc::c_ulong = 0x6601;
-    pub const FIONCLEX: libc::c_ulong = 0x6600;
-}
-pub use self::consts::*;
-
-#[cfg(any(target_os = "macos",
-          target_os = "ios",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "bitrig",
-          target_os = "openbsd"))]
-pub const MSG_DONTWAIT: libc::c_int = 0x80;
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub const MSG_DONTWAIT: libc::c_int = 0x40;
+pub const FIOCLEX: libc::c_ulong = 0x6601;
 
 pub const WNOHANG: libc::c_int = 1;
 
@@ -122,14 +107,14 @@ pub struct passwd {
     pub pw_shell: *mut libc::c_char,
 }
 
+// This is really a function pointer (or a union of multiple function
+// pointers), except for constants like SIG_DFL.
+pub type sighandler_t = *mut libc::c_void;
+
+pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
+pub const SIG_ERR: sighandler_t = !0 as sighandler_t;
+
 extern {
-    pub fn gettimeofday(timeval: *mut libc::timeval,
-                        tzp: *mut libc::c_void) -> libc::c_int;
-    pub fn select(nfds: libc::c_int,
-                  readfds: *mut fd_set,
-                  writefds: *mut fd_set,
-                  errorfds: *mut fd_set,
-                  timeout: *mut libc::timeval) -> libc::c_int;
     pub fn getsockopt(sockfd: libc::c_int,
                       level: libc::c_int,
                       optname: libc::c_int,
@@ -141,14 +126,21 @@ extern {
     pub fn waitpid(pid: libc::pid_t, status: *mut libc::c_int,
                    options: libc::c_int) -> libc::pid_t;
 
+    pub fn raise(signum: libc::c_int) -> libc::c_int;
+
     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 sigaltstack(ss: *const sigaltstack,
+                       oss: *mut sigaltstack) -> libc::c_int;
+
+    #[cfg(not(target_os = "android"))]
     pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
 
+    pub fn pthread_sigmask(how: libc::c_int, set: *const sigset_t,
+                           oldset: *mut sigset_t) -> libc::c_int;
+
     #[cfg(not(target_os = "ios"))]
     pub fn getpwuid_r(uid: libc::uid_t,
                       pwd: *mut passwd,
@@ -165,161 +157,188 @@ extern {
                     -> *mut libc::c_char;
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-mod select {
-    pub const FD_SETSIZE: usize = 1024;
-
-    #[repr(C)]
-    pub struct fd_set {
-        fds_bits: [i32; (FD_SETSIZE / 32)]
-    }
-
-    pub fn fd_set(set: &mut fd_set, fd: i32) {
-        set.fds_bits[(fd / 32) as usize] |= 1 << ((fd % 32) as usize);
-    }
-}
-
-#[cfg(any(target_os = "android",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "bitrig",
-          target_os = "openbsd",
-          target_os = "linux"))]
-mod select {
-    use usize;
-    use libc;
-
-    pub const FD_SETSIZE: usize = 1024;
-
-    #[repr(C)]
-    pub struct fd_set {
-        // FIXME: shouldn't this be a c_ulong?
-        fds_bits: [libc::uintptr_t; (FD_SETSIZE / usize::BITS)]
-    }
-
-    pub fn fd_set(set: &mut fd_set, fd: i32) {
-        let fd = fd as usize;
-        set.fds_bits[fd / usize::BITS] |= 1 << (fd % usize::BITS);
-    }
+// Ugh. This is only available as an inline until Android API 21.
+#[cfg(target_os = "android")]
+pub unsafe fn sigemptyset(set: *mut sigset_t) -> libc::c_int {
+    use intrinsics;
+    intrinsics::write_bytes(set, 0, 1);
+    return 0;
 }
 
-#[cfg(any(all(target_os = "linux",
-              any(target_arch = "x86",
-                  target_arch = "x86_64",
-                  target_arch = "arm",
-                  target_arch = "aarch64")),
+#[cfg(any(target_os = "linux",
           target_os = "android"))]
-mod signal {
+mod signal_os {
+    pub use self::arch::{SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_SETMASK,
+                         sigaction, sigaltstack};
     use libc;
 
-    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
-    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00000002;
-    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
-    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
-    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
-    pub const SA_RESTART: libc::c_ulong = 0x10000000;
-    pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
-    pub const SIGCHLD: libc::c_int = 17;
-
-    // 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.
+    #[cfg(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    pub const SIGSTKSZ: libc::size_t = 8192;
+
+    // This is smaller on musl and Android, but no harm in being generous.
+    #[cfg(any(target_arch = "aarch64",
+              target_arch = "powerpc"))]
+    pub const SIGSTKSZ: libc::size_t = 16384;
+
+    // This definition is intentionally a subset of the C structure: the
+    // fields after si_code are actually a giant union. We're only
+    // interested in si_addr for this module, though.
     #[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,
+        _signo: libc::c_int,
+        _errno: libc::c_int,
+        _code: libc::c_int,
+        // This structure will need extra padding here for MIPS64.
+        pub si_addr: *mut libc::c_void
     }
 
+    #[cfg(all(target_os = "linux", target_pointer_width = "32"))]
     #[repr(C)]
-    pub struct sigaction {
-        pub sa_handler: extern fn(libc::c_int),
-        pub sa_mask: sigset_t,
-        pub sa_flags: libc::c_ulong,
-        sa_restorer: *mut libc::c_void,
-    }
-
-    unsafe impl ::marker::Send for sigaction { }
-    unsafe impl ::marker::Sync for sigaction { }
-
-    #[repr(C)]
-    #[cfg(target_pointer_width = "32")]
     pub struct sigset_t {
         __val: [libc::c_ulong; 32],
     }
 
+    #[cfg(all(target_os = "linux", target_pointer_width = "64"))]
     #[repr(C)]
-    #[cfg(target_pointer_width = "64")]
     pub struct sigset_t {
         __val: [libc::c_ulong; 16],
     }
-}
 
-#[cfg(all(target_os = "linux",
-          any(target_arch = "mips",
-              target_arch = "mipsel",
-              target_arch = "powerpc")))]
-mod signal {
-    use libc;
-
-    pub const SA_NOCLDSTOP: libc::c_ulong = 0x00000001;
-    pub const SA_NOCLDWAIT: libc::c_ulong = 0x00010000;
-    pub const SA_NODEFER: libc::c_ulong = 0x40000000;
-    pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
-    pub const SA_RESETHAND: libc::c_ulong = 0x80000000;
-    pub const SA_RESTART: libc::c_ulong = 0x10000000;
-    pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
-    pub const SIGCHLD: libc::c_int = 18;
-
-    // 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,
+    // Android for MIPS has a 128-bit sigset_t, but we don't currently
+    // support it. Android for AArch64 technically has a structure of a
+    // single ulong.
+    #[cfg(target_os = "android")]
+    pub type sigset_t = libc::c_ulong;
+
+    #[cfg(any(target_arch = "x86",
+              target_arch = "x86_64",
+              target_arch = "powerpc",
+              target_arch = "arm",
+              target_arch = "aarch64"))]
+    mod arch {
+        use libc;
+        use super::super::sighandler_t;
+        use super::sigset_t;
+
+        pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
+        pub const SA_SIGINFO: libc::c_ulong = 0x00000004;
+
+        pub const SIGBUS: libc::c_int = 7;
+
+        pub const SIG_SETMASK: libc::c_int = 2;
+
+        #[cfg(target_os = "linux")]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_ulong,
+            _restorer: *mut libc::c_void,
+        }
+
+        #[cfg(all(target_os = "android", target_pointer_width = "32"))]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_flags: libc::c_ulong,
+            _restorer: *mut libc::c_void,
+            pub sa_mask: sigset_t,
+        }
+
+        #[cfg(all(target_os = "android", target_pointer_width = "64"))]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_flags: libc::c_uint,
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            _restorer: *mut libc::c_void,
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_flags: libc::c_int,
+            pub ss_size: libc::size_t
+        }
     }
 
-    #[repr(C)]
-    pub struct sigaction {
-        pub sa_flags: libc::c_uint,
-        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],
-    }
-
-    unsafe impl ::marker::Send for sigaction { }
-    unsafe impl ::marker::Sync for sigaction { }
-
-    #[repr(C)]
-    pub struct sigset_t {
-        __val: [libc::c_ulong; 32],
+    #[cfg(any(target_arch = "mips",
+              target_arch = "mipsel"))]
+    mod arch {
+        use libc;
+        use super::super::sighandler_t;
+        use super::sigset_t;
+
+        pub const SA_ONSTACK: libc::c_ulong = 0x08000000;
+        pub const SA_SIGINFO: libc::c_ulong = 0x00000008;
+
+        pub const SIGBUS: libc::c_int = 10;
+
+        pub const SIG_SETMASK: libc::c_int = 3;
+
+        #[cfg(all(target_os = "linux", not(target_env = "musl")))]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_flags: libc::c_uint,
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            _restorer: *mut libc::c_void,
+            _resv: [libc::c_int; 1],
+        }
+
+        #[cfg(target_env = "musl")]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_ulong,
+            _restorer: *mut libc::c_void,
+        }
+
+        #[cfg(target_os = "android")]
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_flags: libc::c_uint,
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_size: libc::size_t,
+            pub ss_flags: libc::c_int,
+        }
     }
 }
 
 #[cfg(any(target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly"))]
-mod signal {
+          target_os = "dragonfly",
+          target_os = "bitrig",
+          target_os = "openbsd"))]
+mod signal_os {
     use libc;
+    use super::sighandler_t;
 
     pub const SA_ONSTACK: libc::c_int = 0x0001;
-    pub const SA_RESTART: libc::c_int = 0x0002;
-    pub const SA_RESETHAND: libc::c_int = 0x0004;
-    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
-    pub const SA_NODEFER: libc::c_int = 0x0010;
-    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
     pub const SA_SIGINFO: libc::c_int = 0x0040;
-    pub const SIGCHLD: libc::c_int = 20;
+
+    pub const SIGBUS: libc::c_int = 10;
+
+    #[cfg(any(target_os = "macos", target_os = "ios"))]
+    pub const SIGSTKSZ: libc::size_t = 131072;
+    // FreeBSD's is actually arch-dependent, but never more than 40960.
+    // No harm in being generous.
+    #[cfg(not(any(target_os = "macos", target_os = "ios")))]
+    pub const SIGSTKSZ: libc::size_t = 40960;
+
+    pub const SIG_SETMASK: libc::c_int = 3;
 
     #[cfg(any(target_os = "macos",
               target_os = "ios"))]
@@ -329,61 +348,53 @@ mod signal {
     pub struct sigset_t {
         bits: [u32; 4],
     }
+    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+    pub type sigset_t = libc::c_uint;
 
     // This structure has more fields, but we're not all that interested in
     // them.
+    #[cfg(any(target_os = "macos", target_os = "ios",
+              target_os = "freebsd", target_os = "dragonfly"))]
+    #[repr(C)]
+    pub struct siginfo {
+        pub _signo: libc::c_int,
+        pub _errno: libc::c_int,
+        pub _code: libc::c_int,
+        pub _pid: libc::pid_t,
+        pub _uid: libc::uid_t,
+        pub _status: libc::c_int,
+        pub si_addr: *mut libc::c_void
+    }
+    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
     #[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,
+        pub si_errno: libc::c_int,
+        pub si_addr: *mut libc::c_void
     }
 
+    #[cfg(any(target_os = "macos", target_os = "ios",
+              target_os = "bitrig", target_os = "openbsd"))]
     #[repr(C)]
     pub struct sigaction {
-        pub sa_handler: extern fn(libc::c_int),
-        pub sa_flags: libc::c_int,
+        pub sa_sigaction: sighandler_t,
         pub sa_mask: sigset_t,
+        pub sa_flags: libc::c_int,
     }
-}
-
-#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
-mod signal {
-    use libc;
-
-    pub const SA_ONSTACK: libc::c_int = 0x0001;
-    pub const SA_RESTART: libc::c_int = 0x0002;
-    pub const SA_RESETHAND: libc::c_int = 0x0004;
-    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
-    pub const SA_NODEFER: libc::c_int = 0x0010;
-    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
-    pub const SA_SIGINFO: libc::c_int = 0x0040;
-    pub const SIGCHLD: libc::c_int = 20;
-
-    pub type sigset_t = libc::c_uint;
 
-    // This structure has more fields, but we're not all that interested in
-    // them.
+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
     #[repr(C)]
-    pub struct siginfo {
-        pub si_signo: libc::c_int,
-        pub si_code: libc::c_int,
-        pub si_errno: libc::c_int,
-        // FIXME: Bitrig has a crazy union here in the siginfo, I think this
-        // layout will still work tho.  The status might be off by the size of
-        // a clock_t by my reading, but we can fix this later.
-        pub pid: libc::pid_t,
-        pub uid: libc::uid_t,
-        pub status: libc::c_int,
+    pub struct sigaction {
+        pub sa_sigaction: sighandler_t,
+        pub sa_flags: libc::c_int,
+        pub sa_mask: sigset_t,
     }
 
     #[repr(C)]
-    pub struct sigaction {
-        pub sa_handler: extern fn(libc::c_int),
-        pub sa_mask: sigset_t,
-        pub sa_flags: libc::c_int,
+    pub struct sigaltstack {
+        pub ss_sp: *mut libc::c_void,
+        pub ss_size: libc::size_t,
+        pub ss_flags: libc::c_int,
     }
 }
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index acf6fbc24e4..695d0ddfaaf 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -17,6 +17,7 @@ use ffi::{OsString, OsStr, CString, CStr};
 use fmt;
 use io::{self, Error, ErrorKind};
 use libc::{self, pid_t, c_void, c_int, gid_t, uid_t};
+use mem;
 use ptr;
 use sys::fd::FileDesc;
 use sys::fs::{File, OpenOptions};
@@ -313,6 +314,23 @@ impl Process {
         if !envp.is_null() {
             *sys::os::environ() = envp as *const _;
         }
+
+        // Reset signal handling so the child process starts in a
+        // standardized state. libstd ignores SIGPIPE, and signal-handling
+        // libraries often set a mask. Child processes inherit ignored
+        // signals and the signal mask from their parent, but most
+        // UNIX programs do not reset these things on their own, so we
+        // need to clean things up now to avoid confusing the program
+        // we're about to run.
+        let mut set: c::sigset_t = mem::uninitialized();
+        if c::sigemptyset(&mut set) != 0 ||
+           c::pthread_sigmask(c::SIG_SETMASK, &set, ptr::null_mut()) != 0 ||
+           libc::funcs::posix01::signal::signal(
+               libc::SIGPIPE, mem::transmute(c::SIG_DFL)
+           ) == mem::transmute(c::SIG_ERR) {
+            fail(&mut output);
+        }
+
         let _ = libc::execvp(*argv, argv);
         fail(&mut output)
     }
@@ -418,3 +436,69 @@ fn translate_status(status: c_int) -> ExitStatus {
         ExitStatus::Signal(imp::WTERMSIG(status))
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use prelude::v1::*;
+
+    use ffi::OsStr;
+    use mem;
+    use ptr;
+    use libc;
+    use slice;
+    use sys::{self, c, cvt, pipe};
+
+    #[cfg(not(target_os = "android"))]
+    extern {
+        fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int;
+    }
+
+    #[cfg(target_os = "android")]
+    unsafe fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int {
+        let raw = slice::from_raw_parts_mut(set as *mut u8, mem::size_of::<c::sigset_t>());
+        let bit = (signum - 1) as usize;
+        raw[bit / 8] |= 1 << (bit % 8);
+        return 0;
+    }
+
+    #[test]
+    fn test_process_mask() {
+        unsafe {
+            // Test to make sure that a signal mask does not get inherited.
+            let cmd = Command::new(OsStr::new("cat"));
+            let (stdin_read, stdin_write) = sys::pipe::anon_pipe().unwrap();
+            let (stdout_read, stdout_write) = sys::pipe::anon_pipe().unwrap();
+
+            let mut set: c::sigset_t = mem::uninitialized();
+            let mut old_set: c::sigset_t = mem::uninitialized();
+            cvt(c::sigemptyset(&mut set)).unwrap();
+            cvt(sigaddset(&mut set, libc::SIGINT)).unwrap();
+            cvt(c::pthread_sigmask(c::SIG_SETMASK, &set, &mut old_set)).unwrap();
+
+            let cat = Process::spawn(&cmd, Stdio::Raw(stdin_read.raw()),
+                                           Stdio::Raw(stdout_write.raw()),
+                                           Stdio::None).unwrap();
+            drop(stdin_read);
+            drop(stdout_write);
+
+            cvt(c::pthread_sigmask(c::SIG_SETMASK, &old_set, ptr::null_mut())).unwrap();
+
+            cvt(libc::funcs::posix88::signal::kill(cat.id() as libc::pid_t, libc::SIGINT)).unwrap();
+            // We need to wait until SIGINT is definitely delivered. The
+            // easiest way is to write something to cat, and try to read it
+            // back: if SIGINT is unmasked, it'll get delivered when cat is
+            // next scheduled.
+            let _ = stdin_write.write(b"Hello");
+            drop(stdin_write);
+
+            // Either EOF or failure (EPIPE) is okay.
+            let mut buf = [0; 5];
+            if let Ok(ret) = stdout_read.read(&mut buf) {
+                assert!(ret == 0);
+            }
+
+            cat.wait().unwrap();
+        }
+    }
+}
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 2bc280d1274..52494a17b9d 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -44,11 +44,12 @@ mod imp {
     use mem;
     use ptr;
     use intrinsics;
-    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
-                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
-                       SIGSTKSZ};
+    use sys::c::{siginfo, sigaction, SIGBUS, SIG_DFL,
+                 SA_SIGINFO, SA_ONSTACK, sigaltstack,
+                 SIGSTKSZ, sighandler_t, raise};
     use libc;
     use libc::funcs::posix88::mman::{mmap, munmap};
+    use libc::funcs::posix01::signal::signal;
     use libc::consts::os::posix88::{SIGSEGV,
                                     PROT_READ,
                                     PROT_WRITE,
@@ -120,7 +121,7 @@ mod imp {
 
     pub unsafe fn make_handler() -> Handler {
         let alt_stack = mmap(ptr::null_mut(),
-                             signal::SIGSTKSZ,
+                             SIGSTKSZ,
                              PROT_READ | PROT_WRITE,
                              MAP_PRIVATE | MAP_ANON,
                              -1,
@@ -143,138 +144,6 @@ mod imp {
     pub unsafe fn drop_handler(handler: &mut Handler) {
         munmap(handler._data, SIGSTKSZ);
     }
-
-    pub type sighandler_t = *mut libc::c_void;
-
-    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
-              all(target_os = "linux", target_arch = "x86_64"),
-              all(target_os = "linux", target_arch = "arm"), // may not match
-              all(target_os = "linux", target_arch = "aarch64"),
-              all(target_os = "linux", target_arch = "mips"), // may not match
-              all(target_os = "linux", target_arch = "mipsel"), // may not match
-              all(target_os = "linux", target_arch = "powerpc"), // may not match
-              target_os = "android"))] // may not match
-    mod signal {
-        use libc;
-        pub use super::sighandler_t;
-
-        pub static SA_ONSTACK: libc::c_int = 0x08000000;
-        pub static SA_SIGINFO: libc::c_int = 0x00000004;
-        pub static SIGBUS: libc::c_int = 7;
-
-        pub static SIGSTKSZ: libc::size_t = 8192;
-
-        pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
-
-        // This definition is not as accurate as it could be, {si_addr} is
-        // actually a giant union. Currently we're only interested in that field,
-        // however.
-        #[repr(C)]
-        pub struct siginfo {
-            si_signo: libc::c_int,
-            si_errno: libc::c_int,
-            si_code: libc::c_int,
-            pub si_addr: *mut libc::c_void
-        }
-
-        #[repr(C)]
-        pub struct sigaction {
-            pub sa_sigaction: sighandler_t,
-            pub sa_mask: sigset_t,
-            pub sa_flags: libc::c_int,
-            sa_restorer: *mut libc::c_void,
-        }
-
-        #[cfg(target_pointer_width = "32")]
-        #[repr(C)]
-        pub struct sigset_t {
-            __val: [libc::c_ulong; 32],
-        }
-        #[cfg(target_pointer_width = "64")]
-        #[repr(C)]
-        pub struct sigset_t {
-            __val: [libc::c_ulong; 16],
-        }
-
-        #[repr(C)]
-        pub struct sigaltstack {
-            pub ss_sp: *mut libc::c_void,
-            pub ss_flags: libc::c_int,
-            pub ss_size: libc::size_t
-        }
-
-    }
-
-    #[cfg(any(target_os = "macos",
-              target_os = "bitrig",
-              target_os = "openbsd"))]
-    mod signal {
-        use libc;
-        pub use super::sighandler_t;
-
-        pub const SA_ONSTACK: libc::c_int = 0x0001;
-        pub const SA_SIGINFO: libc::c_int = 0x0040;
-        pub const SIGBUS: libc::c_int = 10;
-
-        #[cfg(target_os = "macos")]
-        pub const SIGSTKSZ: libc::size_t = 131072;
-        #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
-        pub const SIGSTKSZ: libc::size_t = 40960;
-
-        pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
-
-        pub type sigset_t = u32;
-
-        // This structure has more fields, but we're not all that interested in
-        // them.
-        #[cfg(target_os = "macos")]
-        #[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,
-            pub si_addr: *mut libc::c_void
-        }
-
-        #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
-        #[repr(C)]
-        pub struct siginfo {
-            pub si_signo: libc::c_int,
-            pub si_code: libc::c_int,
-            pub si_errno: libc::c_int,
-            //union
-            pub si_addr: *mut libc::c_void
-        }
-
-        #[repr(C)]
-        pub struct sigaltstack {
-            pub ss_sp: *mut libc::c_void,
-            pub ss_size: libc::size_t,
-            pub ss_flags: libc::c_int
-        }
-
-        #[repr(C)]
-        pub struct sigaction {
-            pub sa_sigaction: sighandler_t,
-            pub sa_mask: sigset_t,
-            pub sa_flags: libc::c_int,
-        }
-    }
-
-    extern {
-        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
-        pub fn raise(signum: libc::c_int) -> libc::c_int;
-
-        pub fn sigaction(signum: libc::c_int,
-                         act: *const sigaction,
-                         oldact: *mut sigaction) -> libc::c_int;
-
-        pub fn sigaltstack(ss: *const sigaltstack,
-                           oss: *mut sigaltstack) -> libc::c_int;
-    }
 }
 
 #[cfg(not(any(target_os = "linux",