diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2017-06-07 18:31:35 -0700 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2017-06-08 07:31:05 -0700 |
| commit | 44e6406f9a29e03280f4e16434c06e1d0abfaffc (patch) | |
| tree | f3e8ce08ebd80311db2dba53b4fcf3c1e30c0a7e /src/libstd/sys | |
| parent | 03eb7109c722117322064390bc66578cde3f7b8e (diff) | |
| download | rust-44e6406f9a29e03280f4e16434c06e1d0abfaffc.tar.gz rust-44e6406f9a29e03280f4e16434c06e1d0abfaffc.zip | |
std: Handle ENOSYS when calling `pipe2`
Should help fix an accidental regression from #39386.
Diffstat (limited to 'src/libstd/sys')
| -rw-r--r-- | src/libstd/sys/unix/pipe.rs | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 706256ff10e..ca5ef4bcfc5 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -11,8 +11,9 @@ use io; use libc::{self, c_int}; use mem; -use sys::{cvt, cvt_r}; +use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; use sys::fd::FileDesc; +use sys::{cvt, cvt_r}; //////////////////////////////////////////////////////////////////////////////// // Anonymous pipes @@ -21,6 +22,9 @@ use sys::fd::FileDesc; pub struct AnonPipe(FileDesc); 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]; // Unfortunately the only known way right now to create atomically set the @@ -31,13 +35,26 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { target_os = "freebsd", target_os = "linux", 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() { - cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?; - return Ok((AnonPipe(FileDesc::new(fds[0])), - AnonPipe(FileDesc::new(fds[1])))); + // 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])), + 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()) })?; |
