about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorTobias Bucher <tobiasbucher5991@gmail.com>2017-01-27 19:45:18 +0100
committerTobias Bucher <tobiasbucher5991@gmail.com>2017-01-27 19:45:18 +0100
commitc31d5b504144c4c542c3042b850cfc3b1066aa38 (patch)
tree90d7339668c7f7f6c5c558471e536031d5d7e2e7 /src/libstd/sys
parentfece9c735678d152da721711f6f4aba1f0b8ab15 (diff)
downloadrust-c31d5b504144c4c542c3042b850cfc3b1066aa38.tar.gz
rust-c31d5b504144c4c542c3042b850cfc3b1066aa38.zip
Use less syscalls in `anon_pipe()`
Save a `ENOSYS` failure from `pipe2` and don't try again.

Use `cvt` instead of `cvt_r` for `pipe2` - `EINTR` is not an error
`pipe2` can return.
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/unix/pipe.rs38
1 files changed, 19 insertions, 19 deletions
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index a8ed415b7f4..a5d60c257ed 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -13,7 +13,8 @@ use io;
 use libc::{self, c_int};
 use mem;
 use ptr;
-use sys::cvt_r;
+use sync::atomic::{AtomicBool, Ordering};
+use sys::{cvt, cvt_r};
 use sys::fd::FileDesc;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -29,34 +30,33 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
     // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
     // 2.6.27, however, and because we support 2.6.18 we must detect this
     // support dynamically.
-    if cfg!(target_os = "linux") {
+    static TRY_PIPE2: AtomicBool = AtomicBool::new(cfg!(target_os = "linux"));
+    if TRY_PIPE2.load(Ordering::Relaxed) {
         weak! { fn pipe2(*mut c_int, c_int) -> c_int }
         if let Some(pipe) = pipe2.get() {
-            match cvt_r(|| unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
-                Ok(_) => {
+            match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
+                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
+                    TRY_PIPE2.store(false, Ordering::Relaxed);
+                    // Fall through
+                },
+                res => {
+                    res?;
                     return Ok((AnonPipe(FileDesc::new(fds[0])),
-                               AnonPipe(FileDesc::new(fds[1]))))
+                               AnonPipe(FileDesc::new(fds[1]))));
                 }
-                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
-                Err(e) => return Err(e),
             }
         }
     }
-    if unsafe { libc::pipe(fds.as_mut_ptr()) == 0 } {
-        let fd0 = FileDesc::new(fds[0]);
-        let fd1 = FileDesc::new(fds[1]);
-        Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?))
-    } else {
-        Err(io::Error::last_os_error())
-    }
+    cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
+
+    let fd0 = FileDesc::new(fds[0]);
+    let fd1 = FileDesc::new(fds[1]);
+    fd0.set_cloexec()?;
+    fd1.set_cloexec()?;
+    Ok((AnonPipe(fd0), AnonPipe(fd1)))
 }
 
 impl AnonPipe {
-    pub fn from_fd(fd: FileDesc) -> io::Result<AnonPipe> {
-        fd.set_cloexec()?;
-        Ok(AnonPipe(fd))
-    }
-
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.read(buf)
     }