Skip to content

Commit a7ac71b

Browse files
committed
Auto merge of #42521 - alexcrichton:enosys, r=cuviper
std: Handle ENOSYS when calling `pipe2` Should help fix an accidental regression from #39386.
2 parents 19193d6 + 44e6406 commit a7ac71b

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

src/libstd/sys/unix/pipe.rs

+23-6
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
use io;
1212
use libc::{self, c_int};
1313
use mem;
14-
use sys::{cvt, cvt_r};
14+
use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
1515
use sys::fd::FileDesc;
16+
use sys::{cvt, cvt_r};
1617

1718
////////////////////////////////////////////////////////////////////////////////
1819
// Anonymous pipes
@@ -21,6 +22,9 @@ use sys::fd::FileDesc;
2122
pub struct AnonPipe(FileDesc);
2223

2324
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
25+
weak! { fn pipe2(*mut c_int, c_int) -> c_int }
26+
static INVALID: AtomicBool = ATOMIC_BOOL_INIT;
27+
2428
let mut fds = [0; 2];
2529

2630
// Unfortunately the only known way right now to create atomically set the
@@ -31,13 +35,26 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
3135
target_os = "freebsd",
3236
target_os = "linux",
3337
target_os = "netbsd",
34-
target_os = "openbsd"))
38+
target_os = "openbsd")) &&
39+
!INVALID.load(Ordering::SeqCst)
3540
{
36-
weak! { fn pipe2(*mut c_int, c_int) -> c_int }
41+
3742
if let Some(pipe) = pipe2.get() {
38-
cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) })?;
39-
return Ok((AnonPipe(FileDesc::new(fds[0])),
40-
AnonPipe(FileDesc::new(fds[1]))));
43+
// Note that despite calling a glibc function here we may still
44+
// get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
45+
// emulate on older kernels, so if you happen to be running on
46+
// an older kernel you may see `pipe2` as a symbol but still not
47+
// see the syscall.
48+
match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
49+
Ok(_) => {
50+
return Ok((AnonPipe(FileDesc::new(fds[0])),
51+
AnonPipe(FileDesc::new(fds[1]))));
52+
}
53+
Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
54+
INVALID.store(true, Ordering::SeqCst);
55+
}
56+
Err(e) => return Err(e),
57+
}
4158
}
4259
}
4360
cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;

0 commit comments

Comments
 (0)