Auto merge of #39386 - tbu-:pr_pipe_less_syscalls, r=alexcrichton

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.
This commit is contained in:
bors 2017-02-02 13:04:53 +00:00
commit d5f54743db

View File

@ -13,7 +13,7 @@ use io;
use libc::{self, c_int};
use mem;
use ptr;
use sys::cvt_r;
use sys::{cvt, cvt_r};
use sys::fd::FileDesc;
////////////////////////////////////////////////////////////////////////////////
@ -29,34 +29,29 @@ 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") {
if cfg!(any(target_os = "dragonfly",
target_os = "freebsd",
target_os = "linux",
target_os = "netbsd",
target_os = "openbsd"))
{
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(_) => {
return Ok((AnonPipe(FileDesc::new(fds[0])),
AnonPipe(FileDesc::new(fds[1]))))
}
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
Err(e) => return Err(e),
}
cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
return Ok((AnonPipe(FileDesc::new(fds[0])),
AnonPipe(FileDesc::new(fds[1]))));
}
}
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)
}