std: Handle ENOSYS when calling pipe2

Should help fix an accidental regression from #39386.
This commit is contained in:
Alex Crichton
2017-06-07 18:31:35 -07:00
parent 03eb7109c7
commit 44e6406f9a

View File

@@ -11,8 +11,9 @@
use io; use io;
use libc::{self, c_int}; use libc::{self, c_int};
use mem; use mem;
use sys::{cvt, cvt_r}; use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use sys::fd::FileDesc; use sys::fd::FileDesc;
use sys::{cvt, cvt_r};
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes // Anonymous pipes
@@ -21,6 +22,9 @@ use sys::fd::FileDesc;
pub struct AnonPipe(FileDesc); pub struct AnonPipe(FileDesc);
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
weak! { fn pipe2(*mut c_int, c_int) -> c_int }
static INVALID: AtomicBool = ATOMIC_BOOL_INIT;
let mut fds = [0; 2]; let mut fds = [0; 2];
// Unfortunately the only known way right now to create atomically set the // Unfortunately the only known way right now to create atomically set the
@@ -31,14 +35,27 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
target_os = "freebsd", target_os = "freebsd",
target_os = "linux", target_os = "linux",
target_os = "netbsd", target_os = "netbsd",
target_os = "openbsd")) target_os = "openbsd")) &&
!INVALID.load(Ordering::SeqCst)
{ {
weak! { fn pipe2(*mut c_int, c_int) -> c_int }
if let Some(pipe) = pipe2.get() { if let Some(pipe) = pipe2.get() {
cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?; // Note that despite calling a glibc function here we may still
// get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
// emulate on older kernels, so if you happen to be running on
// an older kernel you may see `pipe2` as a symbol but still not
// see the syscall.
match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
Ok(_) => {
return Ok((AnonPipe(FileDesc::new(fds[0])), 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) => {
INVALID.store(true, Ordering::SeqCst);
}
Err(e) => return Err(e),
}
}
} }
cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?; cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;