11
11
use io;
12
12
use libc:: { self , c_int} ;
13
13
use mem;
14
- use sys :: { cvt , cvt_r } ;
14
+ use sync :: atomic :: { AtomicBool , ATOMIC_BOOL_INIT , Ordering } ;
15
15
use sys:: fd:: FileDesc ;
16
+ use sys:: { cvt, cvt_r} ;
16
17
17
18
////////////////////////////////////////////////////////////////////////////////
18
19
// Anonymous pipes
@@ -21,6 +22,9 @@ use sys::fd::FileDesc;
21
22
pub struct AnonPipe ( FileDesc ) ;
22
23
23
24
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
+
24
28
let mut fds = [ 0 ; 2 ] ;
25
29
26
30
// Unfortunately the only known way right now to create atomically set the
@@ -31,13 +35,26 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
31
35
target_os = "freebsd" ,
32
36
target_os = "linux" ,
33
37
target_os = "netbsd" ,
34
- target_os = "openbsd" ) )
38
+ target_os = "openbsd" ) ) &&
39
+ !INVALID . load ( Ordering :: SeqCst )
35
40
{
36
- weak ! { fn pipe2 ( * mut c_int , c_int ) -> c_int }
41
+
37
42
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
+ }
41
58
}
42
59
}
43
60
cvt ( unsafe { libc:: pipe ( fds. as_mut_ptr ( ) ) } ) ?;
0 commit comments