@@ -54,56 +54,47 @@ impl Socket {
5454
5555 pub fn new_raw ( fam : c_int , ty : c_int ) -> io:: Result < Socket > {
5656 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) ;
7568
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 ) ?;
8073
81- Ok ( socket)
74+ Ok ( socket)
75+ }
76+ }
8277 }
8378 }
8479
8580 pub fn new_pair ( fam : c_int , ty : c_int ) -> io:: Result < ( Socket , Socket ) > {
8681 unsafe {
8782 let mut fds = [ 0 , 0 ] ;
8883
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) ) )
9896 }
9997 }
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) ) )
10798 }
10899 }
109100
@@ -177,30 +168,20 @@ impl Socket {
177168 pub fn accept ( & self , storage : * mut sockaddr , len : * mut socklen_t ) -> io:: Result < Socket > {
178169 // Unfortunately the only known way right now to accept a socket and
179170 // 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) )
197183 }
198184 }
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) )
204185 }
205186
206187 pub fn duplicate ( & self ) -> io:: Result < Socket > {
0 commit comments