@@ -13,7 +13,8 @@ use io;
13
13
use libc:: { self , c_int} ;
14
14
use mem;
15
15
use ptr;
16
- use sys:: cvt_r;
16
+ use sync:: atomic:: { AtomicBool , Ordering } ;
17
+ use sys:: { cvt, cvt_r} ;
17
18
use sys:: fd:: FileDesc ;
18
19
19
20
////////////////////////////////////////////////////////////////////////////////
@@ -29,34 +30,33 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
29
30
// CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
30
31
// 2.6.27, however, and because we support 2.6.18 we must detect this
31
32
// support dynamically.
32
- if cfg ! ( target_os = "linux" ) {
33
+ static TRY_PIPE2 : AtomicBool = AtomicBool :: new ( cfg ! ( target_os = "linux" ) ) ;
34
+ if TRY_PIPE2 . load ( Ordering :: Relaxed ) {
33
35
weak ! { fn pipe2( * mut c_int, c_int) -> c_int }
34
36
if let Some ( pipe) = pipe2. get ( ) {
35
- match cvt_r ( || unsafe { pipe ( fds. as_mut_ptr ( ) , libc:: O_CLOEXEC ) } ) {
36
- Ok ( _) => {
37
+ match cvt ( unsafe { pipe ( fds. as_mut_ptr ( ) , libc:: O_CLOEXEC ) } ) {
38
+ Err ( ref e) if e. raw_os_error ( ) == Some ( libc:: ENOSYS ) => {
39
+ TRY_PIPE2 . store ( false , Ordering :: Relaxed ) ;
40
+ // Fall through
41
+ } ,
42
+ res => {
43
+ res?;
37
44
return Ok ( ( AnonPipe ( FileDesc :: new ( fds[ 0 ] ) ) ,
38
- AnonPipe ( FileDesc :: new ( fds[ 1 ] ) ) ) )
45
+ AnonPipe ( FileDesc :: new ( fds[ 1 ] ) ) ) ) ;
39
46
}
40
- Err ( ref e) if e. raw_os_error ( ) == Some ( libc:: ENOSYS ) => { }
41
- Err ( e) => return Err ( e) ,
42
47
}
43
48
}
44
49
}
45
- if unsafe { libc:: pipe ( fds. as_mut_ptr ( ) ) == 0 } {
46
- let fd0 = FileDesc :: new ( fds [ 0 ] ) ;
47
- let fd1 = FileDesc :: new ( fds[ 1 ] ) ;
48
- Ok ( ( AnonPipe :: from_fd ( fd0 ) ? , AnonPipe :: from_fd ( fd1 ) ? ) )
49
- } else {
50
- Err ( io :: Error :: last_os_error ( ) )
51
- }
50
+ cvt ( unsafe { libc:: pipe ( fds. as_mut_ptr ( ) ) } ) ? ;
51
+
52
+ let fd0 = FileDesc :: new ( fds[ 0 ] ) ;
53
+ let fd1 = FileDesc :: new ( fds [ 1 ] ) ;
54
+ fd0 . set_cloexec ( ) ? ;
55
+ fd1 . set_cloexec ( ) ? ;
56
+ Ok ( ( AnonPipe ( fd0 ) , AnonPipe ( fd1 ) ) )
52
57
}
53
58
54
59
impl AnonPipe {
55
- pub fn from_fd ( fd : FileDesc ) -> io:: Result < AnonPipe > {
56
- fd. set_cloexec ( ) ?;
57
- Ok ( AnonPipe ( fd) )
58
- }
59
-
60
60
pub fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
61
61
self . 0 . read ( buf)
62
62
}
0 commit comments