@@ -54,56 +54,47 @@ impl Socket {
54
54
55
55
pub fn new_raw ( fam : c_int , ty : c_int ) -> io:: Result < Socket > {
56
56
unsafe {
57
- // On linux we first attempt to pass the SOCK_CLOEXEC flag to
58
- // atomically create the socket and set it as CLOEXEC. Support for
59
- // this option, however, was added in 2.6.27, and we still support
60
- // 2.6.18 as a kernel, so if the returned error is EINVAL we
61
- // fallthrough to the fallback.
62
- #[ cfg( target_os = "linux" ) ]
63
- {
64
- match cvt ( libc:: socket ( fam, ty | libc:: SOCK_CLOEXEC , 0 ) ) {
65
- Ok ( fd) => return Ok ( Socket ( FileDesc :: new ( fd) ) ) ,
66
- Err ( ref e) if e. raw_os_error ( ) == Some ( libc:: EINVAL ) => { }
67
- Err ( e) => return Err ( e) ,
68
- }
69
- }
70
-
71
- let fd = cvt ( libc:: socket ( fam, ty, 0 ) ) ?;
72
- let fd = FileDesc :: new ( fd) ;
73
- fd. set_cloexec ( ) ?;
74
- let socket = Socket ( fd) ;
57
+ cfg_if:: cfg_if! {
58
+ if #[ cfg( target_os = "linux" ) ] {
59
+ // On Linux we pass the SOCK_CLOEXEC flag to atomically create
60
+ // the socket and set it as CLOEXEC, added in 2.6.27.
61
+ let fd = cvt( libc:: socket( fam, ty | libc:: SOCK_CLOEXEC , 0 ) ) ?;
62
+ Ok ( Socket ( FileDesc :: new( fd) ) )
63
+ } else {
64
+ let fd = cvt( libc:: socket( fam, ty, 0 ) ) ?;
65
+ let fd = FileDesc :: new( fd) ;
66
+ fd. set_cloexec( ) ?;
67
+ let socket = Socket ( fd) ;
75
68
76
- // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt`
77
- // flag to disable `SIGPIPE` emission on socket.
78
- #[ cfg( target_vendor = "apple" ) ]
79
- setsockopt ( & socket, libc:: SOL_SOCKET , libc:: SO_NOSIGPIPE , 1 ) ?;
69
+ // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt`
70
+ // flag to disable `SIGPIPE` emission on socket.
71
+ #[ cfg( target_vendor = "apple" ) ]
72
+ setsockopt( & socket, libc:: SOL_SOCKET , libc:: SO_NOSIGPIPE , 1 ) ?;
80
73
81
- Ok ( socket)
74
+ Ok ( socket)
75
+ }
76
+ }
82
77
}
83
78
}
84
79
85
80
pub fn new_pair ( fam : c_int , ty : c_int ) -> io:: Result < ( Socket , Socket ) > {
86
81
unsafe {
87
82
let mut fds = [ 0 , 0 ] ;
88
83
89
- // Like above, see if we can set cloexec atomically
90
- #[ cfg( target_os = "linux" ) ]
91
- {
92
- match cvt ( libc:: socketpair ( fam, ty | libc:: SOCK_CLOEXEC , 0 , fds. as_mut_ptr ( ) ) ) {
93
- Ok ( _) => {
94
- return Ok ( ( Socket ( FileDesc :: new ( fds[ 0 ] ) ) , Socket ( FileDesc :: new ( fds[ 1 ] ) ) ) ) ;
95
- }
96
- Err ( ref e) if e. raw_os_error ( ) == Some ( libc:: EINVAL ) => { }
97
- Err ( e) => return Err ( e) ,
84
+ cfg_if:: cfg_if! {
85
+ if #[ cfg( target_os = "linux" ) ] {
86
+ // Like above, set cloexec atomically
87
+ cvt( libc:: socketpair( fam, ty | libc:: SOCK_CLOEXEC , 0 , fds. as_mut_ptr( ) ) ) ?;
88
+ Ok ( ( Socket ( FileDesc :: new( fds[ 0 ] ) ) , Socket ( FileDesc :: new( fds[ 1 ] ) ) ) )
89
+ } else {
90
+ cvt( libc:: socketpair( fam, ty, 0 , fds. as_mut_ptr( ) ) ) ?;
91
+ let a = FileDesc :: new( fds[ 0 ] ) ;
92
+ let b = FileDesc :: new( fds[ 1 ] ) ;
93
+ a. set_cloexec( ) ?;
94
+ b. set_cloexec( ) ?;
95
+ Ok ( ( Socket ( a) , Socket ( b) ) )
98
96
}
99
97
}
100
-
101
- cvt ( libc:: socketpair ( fam, ty, 0 , fds. as_mut_ptr ( ) ) ) ?;
102
- let a = FileDesc :: new ( fds[ 0 ] ) ;
103
- let b = FileDesc :: new ( fds[ 1 ] ) ;
104
- a. set_cloexec ( ) ?;
105
- b. set_cloexec ( ) ?;
106
- Ok ( ( Socket ( a) , Socket ( b) ) )
107
98
}
108
99
}
109
100
@@ -177,30 +168,20 @@ impl Socket {
177
168
pub fn accept ( & self , storage : * mut sockaddr , len : * mut socklen_t ) -> io:: Result < Socket > {
178
169
// Unfortunately the only known way right now to accept a socket and
179
170
// atomically set the CLOEXEC flag is to use the `accept4` syscall on
180
- // Linux. This was added in 2.6.28, however, and because we support
181
- // 2.6.18 we must detect this support dynamically.
182
- #[ cfg( target_os = "linux" ) ]
183
- {
184
- syscall ! {
185
- fn accept4(
186
- fd: c_int,
187
- addr: * mut sockaddr,
188
- addr_len: * mut socklen_t,
189
- flags: c_int
190
- ) -> c_int
191
- }
192
- let res = cvt_r ( || unsafe { accept4 ( self . 0 . raw ( ) , storage, len, libc:: SOCK_CLOEXEC ) } ) ;
193
- match res {
194
- Ok ( fd) => return Ok ( Socket ( FileDesc :: new ( fd) ) ) ,
195
- Err ( ref e) if e. raw_os_error ( ) == Some ( libc:: ENOSYS ) => { }
196
- Err ( e) => return Err ( e) ,
171
+ // Linux. This was added in 2.6.28, glibc 2.10 and musl 0.9.5.
172
+ cfg_if:: cfg_if! {
173
+ if #[ cfg( target_os = "linux" ) ] {
174
+ let fd = cvt_r( || unsafe {
175
+ libc:: accept4( self . 0 . raw( ) , storage, len, libc:: SOCK_CLOEXEC )
176
+ } ) ?;
177
+ Ok ( Socket ( FileDesc :: new( fd) ) )
178
+ } else {
179
+ let fd = cvt_r( || unsafe { libc:: accept( self . 0 . raw( ) , storage, len) } ) ?;
180
+ let fd = FileDesc :: new( fd) ;
181
+ fd. set_cloexec( ) ?;
182
+ Ok ( Socket ( fd) )
197
183
}
198
184
}
199
-
200
- let fd = cvt_r ( || unsafe { libc:: accept ( self . 0 . raw ( ) , storage, len) } ) ?;
201
- let fd = FileDesc :: new ( fd) ;
202
- fd. set_cloexec ( ) ?;
203
- Ok ( Socket ( fd) )
204
185
}
205
186
206
187
pub fn duplicate ( & self ) -> io:: Result < Socket > {
0 commit comments