Skip to content

Commit c31d5b5

Browse files
committed
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.
1 parent fece9c7 commit c31d5b5

File tree

1 file changed

+19
-19
lines changed

1 file changed

+19
-19
lines changed

src/libstd/sys/unix/pipe.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use io;
1313
use libc::{self, c_int};
1414
use mem;
1515
use ptr;
16-
use sys::cvt_r;
16+
use sync::atomic::{AtomicBool, Ordering};
17+
use sys::{cvt, cvt_r};
1718
use sys::fd::FileDesc;
1819

1920
////////////////////////////////////////////////////////////////////////////////
@@ -29,34 +30,33 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
2930
// CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
3031
// 2.6.27, however, and because we support 2.6.18 we must detect this
3132
// support dynamically.
32-
if cfg!(target_os = "linux") {
33+
static TRY_PIPE2: AtomicBool = AtomicBool::new(cfg!(target_os = "linux"));
34+
if TRY_PIPE2.load(Ordering::Relaxed) {
3335
weak! { fn pipe2(*mut c_int, c_int) -> c_int }
3436
if let Some(pipe) = pipe2.get() {
35-
match cvt_r(|| unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
36-
Ok(_) => {
37+
match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
38+
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
39+
TRY_PIPE2.store(false, Ordering::Relaxed);
40+
// Fall through
41+
},
42+
res => {
43+
res?;
3744
return Ok((AnonPipe(FileDesc::new(fds[0])),
38-
AnonPipe(FileDesc::new(fds[1]))))
45+
AnonPipe(FileDesc::new(fds[1]))));
3946
}
40-
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
41-
Err(e) => return Err(e),
4247
}
4348
}
4449
}
45-
if unsafe { libc::pipe(fds.as_mut_ptr()) == 0 } {
46-
let fd0 = FileDesc::new(fds[0]);
47-
let fd1 = FileDesc::new(fds[1]);
48-
Ok((AnonPipe::from_fd(fd0)?, AnonPipe::from_fd(fd1)?))
49-
} else {
50-
Err(io::Error::last_os_error())
51-
}
50+
cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
51+
52+
let fd0 = FileDesc::new(fds[0]);
53+
let fd1 = FileDesc::new(fds[1]);
54+
fd0.set_cloexec()?;
55+
fd1.set_cloexec()?;
56+
Ok((AnonPipe(fd0), AnonPipe(fd1)))
5257
}
5358

5459
impl AnonPipe {
55-
pub fn from_fd(fd: FileDesc) -> io::Result<AnonPipe> {
56-
fd.set_cloexec()?;
57-
Ok(AnonPipe(fd))
58-
}
59-
6060
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
6161
self.0.read(buf)
6262
}

0 commit comments

Comments
 (0)