summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md5
-rw-r--r--src/unistd.rs39
2 files changed, 35 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4238ed74..3f8f54de 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,11 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
+### Changed
+- `pipe2` now calls `libc::pipe2` where available. Previously it was emulated
+ using `pipe`, which meant that setting `O_CLOEXEC` was not atomic.
+ ([#427](https://github.com/nix-rust/nix/pull/427))
+
## [0.7.0] 2016-09-09
### Added
diff --git a/src/unistd.rs b/src/unistd.rs
index 74d74c9c..1b2175ea 100644
--- a/src/unistd.rs
+++ b/src/unistd.rs
@@ -1,8 +1,8 @@
//! Standard symbolic constants and types
//!
use {Errno, Error, Result, NixPath};
-use fcntl::{fcntl, OFlag, O_NONBLOCK, O_CLOEXEC, FD_CLOEXEC};
-use fcntl::FcntlArg::{F_SETFD, F_SETFL};
+use fcntl::{fcntl, OFlag, O_CLOEXEC, FD_CLOEXEC};
+use fcntl::FcntlArg::F_SETFD;
use libc::{self, c_char, c_void, c_int, c_uint, size_t, pid_t, off_t, uid_t, gid_t, mode_t};
use std::mem;
use std::ffi::{CString, CStr, OsString};
@@ -360,21 +360,42 @@ pub fn pipe() -> Result<(RawFd, RawFd)> {
}
}
+// libc only defines `pipe2` in `libc::notbsd`.
+#[cfg(any(target_os = "linux",
+ target_os = "android",
+ target_os = "emscripten"))]
pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
- unsafe {
- let mut fds: [c_int; 2] = mem::uninitialized();
+ let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
- let res = libc::pipe(fds.as_mut_ptr());
+ let res = unsafe { libc::pipe2(fds.as_mut_ptr(), flags.bits()) };
- try!(Errno::result(res));
+ try!(Errno::result(res));
+
+ Ok((fds[0], fds[1]))
+}
- try!(pipe2_setflags(fds[0], fds[1], flags));
+#[cfg(not(any(target_os = "linux",
+ target_os = "android",
+ target_os = "emscripten")))]
+pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
+ let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
- Ok((fds[0], fds[1]))
- }
+ let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
+
+ try!(Errno::result(res));
+
+ try!(pipe2_setflags(fds[0], fds[1], flags));
+
+ Ok((fds[0], fds[1]))
}
+#[cfg(not(any(target_os = "linux",
+ target_os = "android",
+ target_os = "emscripten")))]
fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
+ use fcntl::O_NONBLOCK;
+ use fcntl::FcntlArg::F_SETFL;
+
let mut res = Ok(0);
if flags.contains(O_CLOEXEC) {