From c1ffefa56aaeef189e075dc14774e7f518b10b67 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 16 Jul 2017 21:22:33 -0700 Subject: [PATCH 1/6] Remove eventfd feature in favor of conditional include --- Cargo.toml | 1 - src/sys/mod.rs | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e768f4a190..d23d2cf2af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,6 @@ exclude = [ ] [features] -eventfd = [] execvpe = [] preadv_pwritev = [] signalfd = [] diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 627f769718..796a00a195 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -9,8 +9,7 @@ pub mod epoll; target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd"))] pub mod event; -// TODO: switch from feature flags to conditional builds -#[cfg(feature = "eventfd")] +#[cfg(target_os = "linux")] pub mod eventfd; #[cfg(target_os = "linux")] From 79ad5fa487d3d746aa3d03dc70bb133b96053d40 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 16 Jul 2017 21:23:55 -0700 Subject: [PATCH 2/6] Remove preadv_pwritev feature in favor of conditional include --- Cargo.toml | 1 - src/sys/uio.rs | 6 +++--- test/sys/test_uio.rs | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d23d2cf2af..bde647acc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ exclude = [ [features] execvpe = [] -preadv_pwritev = [] signalfd = [] [dependencies] diff --git a/src/sys/uio.rs b/src/sys/uio.rs index 5af1093070..edca8cb4ff 100644 --- a/src/sys/uio.rs +++ b/src/sys/uio.rs @@ -18,7 +18,7 @@ pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result { Errno::result(res).map(|r| r as usize) } -#[cfg(feature = "preadv_pwritev")] +#[cfg(target_os = "linux")] pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>], offset: off_t) -> Result { let res = unsafe { @@ -28,7 +28,7 @@ pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>], Errno::result(res).map(|r| r as usize) } -#[cfg(feature = "preadv_pwritev")] +#[cfg(target_os = "linux")] pub fn preadv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>], offset: off_t) -> Result { let res = unsafe { @@ -57,7 +57,7 @@ pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result{ } #[repr(C)] -pub struct IoVec(libc::iovec, PhantomData); +pub struct IoVec(libc::iovec, PhantomData); impl IoVec { #[inline] diff --git a/test/sys/test_uio.rs b/test/sys/test_uio.rs index 90cda56f5d..d805b3b399 100644 --- a/test/sys/test_uio.rs +++ b/test/sys/test_uio.rs @@ -129,7 +129,7 @@ fn test_pread() { } #[test] -#[cfg(feature = "preadv_pwritev")] +#[cfg(target_os = "linux")] fn test_pwritev() { use std::io::Read; @@ -159,7 +159,7 @@ fn test_pwritev() { } #[test] -#[cfg(feature = "preadv_pwritev")] +#[cfg(target_os = "linux")] fn test_preadv() { use std::io::Write; From 74ea3c7220e616ada07544d9d82d39acd12c2588 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 16 Jul 2017 21:25:50 -0700 Subject: [PATCH 3/6] Remove signalfd feature in favor of conditional compilation Note that this is now only available for Linux as support is missing in libc for Android (see rust-lang/libc#671). As part of this work the SIGUSR2 signal mutex was altered to be a general signal mutex. This is because all signal handling is shared across all threads in the Rust test harness, so if you alter one signal, depending on whether it's additive or may overwrite the mask for other signals, it could break the other ones. Instead of putting this on the user, just broaden the scope of the mutex so that any altering of signal handling needs to use it. --- Cargo.toml | 7 ------- src/sys/mod.rs | 4 ++-- src/sys/signalfd.rs | 10 +++------- test/sys/mod.rs | 2 ++ test/sys/test_aio.rs | 4 ++-- test/sys/test_signalfd.rs | 26 ++++++++++++++++++++++++++ test/test.rs | 6 +++--- test/test_signalfd.rs | 30 ------------------------------ 8 files changed, 38 insertions(+), 51 deletions(-) create mode 100644 test/sys/test_signalfd.rs delete mode 100644 test/test_signalfd.rs diff --git a/Cargo.toml b/Cargo.toml index bde647acc2..3fdf280254 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ exclude = [ [features] execvpe = [] -signalfd = [] [dependencies] libc = "0.2.25" @@ -36,12 +35,6 @@ nix-test = { path = "nix-test", version = "0.0.1" } name = "test" path = "test/test.rs" -[[test]] -name = "test-signalfd" -path = "test/test_signalfd.rs" -harness = false -test = true - [[test]] name = "test-mount" path = "test/test_mount.rs" diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 796a00a195..9636f93da0 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -23,8 +23,8 @@ pub mod sendfile; pub mod signal; -#[cfg(any(target_os = "linux", target_os = "android"))] -#[cfg(feature = "signalfd")] +// FIXME: Add to Android once libc#671 lands in a release +#[cfg(target_os = "linux")] pub mod signalfd; pub mod socket; diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index a3dfb6bec1..fcf2efa90c 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -60,12 +60,10 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result { /// # Examples /// /// ``` -/// use nix::sys::signalfd::*; -/// +/// # use nix::sys::signalfd::*; +/// // Set the thread to block the SIGUSR1 signal, otherwise the default handler will be used /// let mut mask = SigSet::empty(); -/// mask.add(signal::SIGUSR1).unwrap(); -/// -/// // Block the signal, otherwise the default handler will be invoked instead. +/// mask.add(signal::SIGUSR1); /// mask.thread_block().unwrap(); /// /// // Signals are queued up on the file descriptor @@ -74,11 +72,9 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result { /// match sfd.read_signal() { /// // we caught a signal /// Ok(Some(sig)) => (), -/// /// // there were no signals waiting (only happens when the SFD_NONBLOCK flag is set, /// // otherwise the read_signal call blocks) /// Ok(None) => (), -/// /// Err(err) => (), // some error happend /// } /// ``` diff --git a/test/sys/mod.rs b/test/sys/mod.rs index 4edb6af036..2ecc36f844 100644 --- a/test/sys/mod.rs +++ b/test/sys/mod.rs @@ -2,6 +2,8 @@ mod test_signal; #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios", target_os = "netbsd", target_os = "macos", target_os = "linux"))] mod test_aio; +#[cfg(target_os = "linux")] +mod test_signalfd; mod test_socket; mod test_sockopt; mod test_termios; diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs index 7e2bef63fe..54ee5a96a8 100644 --- a/test/sys/test_aio.rs +++ b/test/sys/test_aio.rs @@ -244,7 +244,7 @@ extern fn sigfunc(_: c_int) { #[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips"), ignore)] fn test_write_sigev_signal() { #[allow(unused_variables)] - let m = ::SIGUSR2_MTX.lock().expect("Mutex got poisoned by another test"); + let m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); let sa = SigAction::new(SigHandler::Handler(sigfunc), SA_RESETHAND, SigSet::empty()); @@ -375,7 +375,7 @@ fn test_lio_listio_nowait() { #[cfg_attr(any(target_arch = "mips", target_env = "musl"), ignore)] fn test_lio_listio_signal() { #[allow(unused_variables)] - let m = ::SIGUSR2_MTX.lock().expect("Mutex got poisoned by another test"); + let m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); const INITIAL: &'static [u8] = b"abcdef123456"; const WBUF: &'static [u8] = b"CDEF"; let rbuf = Rc::new(vec![0; 4].into_boxed_slice()); diff --git a/test/sys/test_signalfd.rs b/test/sys/test_signalfd.rs new file mode 100644 index 0000000000..6d65e6a04c --- /dev/null +++ b/test/sys/test_signalfd.rs @@ -0,0 +1,26 @@ +#[test] +fn test_signalfd() { + use nix::sys::signalfd::SignalFd; + use nix::sys::signal::{self, raise, Signal, SigSet}; + + // Grab the mutex for altering signals so we don't interfere with other tests. + #[allow(unused_variables)] + let m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test"); + + // Block the SIGUSR1 signal from automatic processing for this thread + let mut mask = SigSet::empty(); + mask.add(signal::SIGUSR1); + mask.thread_block().unwrap(); + + let mut fd = SignalFd::new(&mask).unwrap(); + + // Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill` + // because `kill` with `getpid` isn't correct during multi-threaded execution like during a + // cargo test session. Instead use `raise` which does the correct thing by default. + raise(signal::SIGUSR1).ok().expect("Error: raise(SIGUSR1) failed"); + + // And now catch that same signal. + let res = fd.read_signal().unwrap().unwrap(); + let signo = Signal::from_c_int(res.ssi_signo as i32).unwrap(); + assert_eq!(signo, signal::SIGUSR1); +} diff --git a/test/test.rs b/test/test.rs index 4c81aa2b73..eb4556fa9f 100644 --- a/test/test.rs +++ b/test/test.rs @@ -11,7 +11,7 @@ extern crate nix_test as nixtest; mod sys; mod test_fcntl; -#[cfg(any(target_os = "linux"))] +#[cfg(target_os = "linux")] mod test_mq; mod test_net; mod test_nix_path; @@ -45,8 +45,8 @@ lazy_static! { /// Any test that creates child processes must grab this mutex, regardless /// of what it does with those children. pub static ref FORK_MTX: Mutex<()> = Mutex::new(()); - /// Any test that registers a SIGUSR2 handler must grab this mutex - pub static ref SIGUSR2_MTX: Mutex<()> = Mutex::new(()); + /// Any test that alters signal handling must grab this mutex. + pub static ref SIGNAL_MTX: Mutex<()> = Mutex::new(()); } #[test] diff --git a/test/test_signalfd.rs b/test/test_signalfd.rs deleted file mode 100644 index 28a6decb9e..0000000000 --- a/test/test_signalfd.rs +++ /dev/null @@ -1,30 +0,0 @@ -extern crate nix; - -#[cfg(feature = "signalfd")] -use nix::sys::signalfd::SignalFd; -#[cfg(feature = "signalfd")] -use nix::sys::signal; -#[cfg(feature = "signalfd")] -use nix::unistd; - -#[cfg(feature = "signalfd")] -fn main() { - print!("test test_signalfd ... "); - - let mut mask = signal::SigSet::empty(); - mask.add(signal::SIGUSR1).unwrap(); - mask.thread_block().unwrap(); - - let mut fd = SignalFd::new(&mask).unwrap(); - - let pid = unistd::getpid(); - signal::kill(pid, signal::SIGUSR1).unwrap(); - - let res = fd.read_signal(); - - assert_eq!(res.unwrap().unwrap().ssi_signo as i32, signal::SIGUSR1); - println!("ok"); -} - -#[cfg(not(feature = "signalfd"))] -fn main() {} From d3f733c264a657ac1e6ac3eb8579ae5c871f38ca Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Sun, 16 Jul 2017 21:38:19 -0700 Subject: [PATCH 4/6] Remove broken execvpe implementation It was broken when enabled, and currently the libc definition is only available for windows. This will be re-added when a new libc is released that supports it across all available platforms --- Cargo.toml | 3 --- src/unistd.rs | 22 ---------------------- test/test_unistd.rs | 4 ---- 3 files changed, 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3fdf280254..c47dfaf69c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,6 @@ exclude = [ "test/**/*" ] -[features] -execvpe = [] - [dependencies] libc = "0.2.25" bitflags = "0.9" diff --git a/src/unistd.rs b/src/unistd.rs index 196232b6c6..25237a07ef 100644 --- a/src/unistd.rs +++ b/src/unistd.rs @@ -1596,9 +1596,6 @@ mod linux { use {Errno, Result, NixPath}; use super::{Uid, Gid}; - #[cfg(feature = "execvpe")] - use std::ffi::CString; - pub fn pivot_root( new_root: &P1, put_old: &P2) -> Result<()> { let res = try!(try!(new_root.with_nix_path(|new_root| { @@ -1643,23 +1640,4 @@ mod linux { Errno::result(res).map(drop) } - - #[inline] - #[cfg(feature = "execvpe")] - pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<()> { - use std::ptr; - use libc::c_char; - - let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect(); - args_p.push(ptr::null()); - - let mut env_p: Vec<*const c_char> = env.iter().map(|s| s.as_ptr()).collect(); - env_p.push(ptr::null()); - - unsafe { - super::ffi::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr()) - }; - - Err(Error::Sys(Errno::last())) - } } diff --git a/test/test_unistd.rs b/test/test_unistd.rs index e6e7b5f211..fd4e327b56 100644 --- a/test/test_unistd.rs +++ b/test/test_unistd.rs @@ -227,10 +227,6 @@ fn test_lseek64() { execve_test_factory!(test_execve, execve, b"/bin/sh", b"/system/bin/sh"); -#[cfg(any(target_os = "linux", target_os = "android"))] -#[cfg(feature = "execvpe")] -execve_test_factory!(test_execvpe, execvpe, b"sh", b"sh"); - #[test] fn test_fpathconf_limited() { let f = tempfile().unwrap(); From 12c71d177ae1851e6b4e66b1975d12f119484a48 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Mon, 17 Jul 2017 11:24:41 -0700 Subject: [PATCH 5/6] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8179de2613..350fc117c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,10 +46,15 @@ This project adheres to [Semantic Versioning](http://semver.org/). Also file system type constants like `nix::sys::statfs::ADFS_SUPER_MAGIC` were removed in favor of the libc equivalent. ([#561](https://github.com/nix-rust/nix/pull/561)) - Revised the termios API including additional tests and documentation and exposed it on iOS. ([#527](https://github.com/nix-rust/nix/pull/527)) +- `eventfd`, `signalfd`, and `pwritev`/`preadv` functionality is now included by default for all + supported platforms. ([#681](https://github.com/nix-rust/nix/pull/561)) ### Removed - Removed `io::Error` from `nix::Error` and the conversion from `nix::Error` to `Errno` ([#614](https://github.com/nix-rust/nix/pull/614)) +- All feature flags have been removed in favor of conditional compilation on supported platforms. + `execvpe` is no longer supported, but this was already broken and will be added back in the next + release. ([#681](https://github.com/nix-rust/nix/pull/561)) ### Fixed - Fixed multiple issues compiling under different archetectures and OSes. From bee13c8c348324f7dabb5eed8d4be17be2c2efd2 Mon Sep 17 00:00:00 2001 From: Bryant Mairs Date: Mon, 17 Jul 2017 22:03:47 -0700 Subject: [PATCH 6/6] Remove unused imports --- test/test_mq.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_mq.rs b/test/test_mq.rs index 60f5bd2e48..08edef78d7 100644 --- a/test/test_mq.rs +++ b/test/test_mq.rs @@ -8,9 +8,6 @@ use std::ffi::CString; use std::str; use libc::c_long; -use nix::unistd::{fork, read, write, pipe}; -use nix::unistd::ForkResult::*; -use nix::sys::wait::*; use nix::errno::Errno::*; use nix::Error::Sys;