@@ -47,15 +47,15 @@ pub struct Acquired {
4747
4848impl Client {
4949 pub fn new ( mut limit : usize ) -> io:: Result < Client > {
50- let client = unsafe { Client :: mk ( ) ? } ;
50+ let client = Client :: mk ( ) ?;
5151
5252 // I don't think the character written here matters, but I could be
5353 // wrong!
5454 const BUFFER : [ u8 ; 128 ] = [ b'|' ; 128 ] ;
5555
5656 let mut write = & client. write ;
5757
58- set_nonblocking ( write. as_raw_fd ( ) , true ) ?;
58+ set_nonblocking ( write. as_fd ( ) , true ) ?;
5959
6060 while limit > 0 {
6161 let n = limit. min ( BUFFER . len ( ) ) ;
@@ -64,39 +64,51 @@ impl Client {
6464 limit -= n;
6565 }
6666
67- set_nonblocking ( write. as_raw_fd ( ) , false ) ?;
67+ set_nonblocking ( write. as_fd ( ) , false ) ?;
6868
6969 Ok ( client)
7070 }
7171
72- unsafe fn mk ( ) -> io:: Result < Client > {
73- let mut pipes = [ 0 ; 2 ] ;
74-
72+ fn mk ( ) -> io:: Result < Client > {
7573 // Attempt atomically-create-with-cloexec if we can on Linux,
7674 // detected by using the `syscall` function in `libc` to try to work
7775 // with as many kernels/glibc implementations as possible.
7876 #[ cfg( target_os = "linux" ) ]
7977 {
8078 static PIPE2_AVAILABLE : AtomicBool = AtomicBool :: new ( true ) ;
81- if PIPE2_AVAILABLE . load ( Ordering :: SeqCst ) {
82- match libc:: syscall ( libc:: SYS_pipe2 , pipes. as_mut_ptr ( ) , libc:: O_CLOEXEC ) {
79+ if PIPE2_AVAILABLE . load ( Ordering :: Relaxed ) {
80+ let mut pipes = [ 0 ; 2 ] ;
81+ match unsafe { libc:: syscall ( libc:: SYS_pipe2 , pipes. as_mut_ptr ( ) , libc:: O_CLOEXEC ) }
82+ {
8383 -1 => {
8484 let err = io:: Error :: last_os_error ( ) ;
8585 if err. raw_os_error ( ) == Some ( libc:: ENOSYS ) {
86- PIPE2_AVAILABLE . store ( false , Ordering :: SeqCst ) ;
86+ PIPE2_AVAILABLE . store ( false , Ordering :: Relaxed ) ;
8787 } else {
8888 return Err ( err) ;
8989 }
9090 }
91- _ => return Ok ( Client :: from_fds ( pipes[ 0 ] , pipes[ 1 ] ) ) ,
91+ _ => unsafe {
92+ return Ok ( Client :: from_fds (
93+ OwnedFd :: from_raw_fd ( pipes[ 0 ] ) ,
94+ OwnedFd :: from_raw_fd ( pipes[ 1 ] ) ,
95+ ) ) ;
96+ } ,
9297 }
9398 }
9499 }
95100
96- cvt ( libc:: pipe ( pipes. as_mut_ptr ( ) ) ) ?;
97- drop ( set_cloexec ( pipes[ 0 ] , true ) ) ;
98- drop ( set_cloexec ( pipes[ 1 ] , true ) ) ;
99- Ok ( Client :: from_fds ( pipes[ 0 ] , pipes[ 1 ] ) )
101+ let ( read, write) = unsafe {
102+ let mut pipes = [ 0 ; 2 ] ;
103+ cvt ( libc:: pipe ( pipes. as_mut_ptr ( ) ) ) ?;
104+ (
105+ OwnedFd :: from_raw_fd ( pipes[ 0 ] ) ,
106+ OwnedFd :: from_raw_fd ( pipes[ 1 ] ) ,
107+ )
108+ } ;
109+ set_cloexec ( read. as_fd ( ) , true ) ?;
110+ set_cloexec ( write. as_fd ( ) , true ) ?;
111+ Ok ( Client :: from_fds ( read, write) )
100112 }
101113
102114 pub ( crate ) unsafe fn open ( s : & str , check_pipe : bool ) -> Result < Client , FromEnvErrorInner > {
@@ -211,18 +223,21 @@ impl Client {
211223 }
212224
213225 Ok ( Some ( Client {
214- read : clone_fd_and_set_cloexec ( read) ?,
215- write : clone_fd_and_set_cloexec ( write) ?,
226+ read : clone_fd_and_set_cloexec ( BorrowedFd :: borrow_raw ( read) ) ?,
227+ write : clone_fd_and_set_cloexec ( BorrowedFd :: borrow_raw ( write) ) ?,
216228 creation_arg,
217229 is_non_blocking : None ,
218230 } ) )
219231 }
220232
221- unsafe fn from_fds ( read : c_int , write : c_int ) -> Client {
233+ fn from_fds ( read : OwnedFd , write : OwnedFd ) -> Client {
222234 Client {
223- read : File :: from_raw_fd ( read) ,
224- write : File :: from_raw_fd ( write) ,
225- creation_arg : ClientCreationArg :: Fds { read, write } ,
235+ creation_arg : ClientCreationArg :: Fds {
236+ read : read. as_raw_fd ( ) ,
237+ write : write. as_raw_fd ( ) ,
238+ } ,
239+ read : read. into ( ) ,
240+ write : write. into ( ) ,
226241 is_non_blocking : None ,
227242 }
228243 }
@@ -304,7 +319,7 @@ impl Client {
304319
305320 if let Some ( is_non_blocking) = self . is_non_blocking . as_ref ( ) {
306321 if !is_non_blocking. load ( Ordering :: Relaxed ) {
307- set_nonblocking ( fifo. as_raw_fd ( ) , true ) ?;
322+ set_nonblocking ( fifo. as_fd ( ) , true ) ?;
308323 is_non_blocking. store ( true , Ordering :: Relaxed ) ;
309324 }
310325 } else {
@@ -357,24 +372,30 @@ impl Client {
357372 Ok ( unsafe { len. assume_init ( ) } as usize )
358373 }
359374
360- pub fn configure ( & self , cmd : & mut Command ) {
361- if matches ! ( self . creation_arg, ClientCreationArg :: Fifo { .. } ) {
362- // We `File::open`ed it when inheriting from environment,
363- // so no need to set cloexec for fifo.
364- return ;
365- }
366- // Here we basically just want to say that in the child process
367- // we'll configure the read/write file descriptors to *not* be
368- // cloexec, so they're inherited across the exec and specified as
369- // integers through `string_arg` above.
370- let read = self . read . as_raw_fd ( ) ;
371- let write = self . write . as_raw_fd ( ) ;
372- unsafe {
373- cmd. pre_exec ( move || {
374- set_cloexec ( read, false ) ?;
375- set_cloexec ( write, false ) ?;
376- Ok ( ( ) )
377- } ) ;
375+ pub fn configure ( self : & Arc < Self > , cmd : & mut Command ) {
376+ match self . creation_arg {
377+ ClientCreationArg :: Fifo { .. } => {
378+ // We `File::open`ed it when inheriting from environment,
379+ // so no need to set cloexec for fifo.
380+ }
381+ ClientCreationArg :: Fds { read, write } => {
382+ // Here we basically just want to say that in the child process
383+ // we'll configure the read/write file descriptors to *not* be
384+ // cloexec, so they're inherited across the exec and specified as
385+ // integers through `string_arg` above.
386+ unsafe {
387+ // Keep a reference to the jobserver alive in the closure so that
388+ // the pipe FDs aren't closed, otherwise `set_cloexec` might end up
389+ // targetting a completely unrelated file descriptor.
390+ let arc = self . clone ( ) ;
391+ cmd. pre_exec ( move || {
392+ let _ = & arc;
393+ set_cloexec ( BorrowedFd :: borrow_raw ( read) , false ) ?;
394+ set_cloexec ( BorrowedFd :: borrow_raw ( write) , false ) ?;
395+ Ok ( ( ) )
396+ } ) ;
397+ }
398+ }
378399 }
379400 }
380401}
@@ -515,34 +536,32 @@ unsafe fn fd_check(fd: c_int, check_pipe: bool) -> Result<(), FromEnvErrorInner>
515536 }
516537}
517538
518- fn clone_fd_and_set_cloexec ( fd : c_int ) -> Result < File , FromEnvErrorInner > {
519- // Safety: fd is a valid fd dand it remains open until returns
520- unsafe { BorrowedFd :: borrow_raw ( fd) }
521- . try_clone_to_owned ( )
539+ fn clone_fd_and_set_cloexec ( fd : BorrowedFd < ' _ > ) -> Result < File , FromEnvErrorInner > {
540+ fd. try_clone_to_owned ( )
522541 . map ( File :: from)
523- . map_err ( |err| FromEnvErrorInner :: CannotOpenFd ( fd, err) )
542+ . map_err ( |err| FromEnvErrorInner :: CannotOpenFd ( fd. as_raw_fd ( ) , err) )
524543}
525544
526- fn set_cloexec ( fd : c_int , set : bool ) -> io:: Result < ( ) > {
545+ fn set_cloexec ( fd : BorrowedFd < ' _ > , set : bool ) -> io:: Result < ( ) > {
527546 unsafe {
528- let previous = cvt ( libc:: fcntl ( fd, libc:: F_GETFD ) ) ?;
547+ let previous = cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_GETFD ) ) ?;
529548 let new = if set {
530549 previous | libc:: FD_CLOEXEC
531550 } else {
532551 previous & !libc:: FD_CLOEXEC
533552 } ;
534553 if new != previous {
535- cvt ( libc:: fcntl ( fd, libc:: F_SETFD , new) ) ?;
554+ cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_SETFD , new) ) ?;
536555 }
537556 Ok ( ( ) )
538557 }
539558}
540559
541- fn set_nonblocking ( fd : c_int , set : bool ) -> io:: Result < ( ) > {
560+ fn set_nonblocking ( fd : BorrowedFd < ' _ > , set : bool ) -> io:: Result < ( ) > {
542561 let status_flag = if set { libc:: O_NONBLOCK } else { 0 } ;
543562
544563 unsafe {
545- cvt ( libc:: fcntl ( fd, libc:: F_SETFL , status_flag) ) ?;
564+ cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_SETFL , status_flag) ) ?;
546565 }
547566
548567 Ok ( ( ) )
@@ -570,12 +589,7 @@ mod test {
570589
571590 use crate :: { test:: run_named_fifo_try_acquire_tests, Client } ;
572591
573- use std:: {
574- fs:: File ,
575- io:: { self , Write } ,
576- os:: unix:: io:: AsRawFd ,
577- sync:: Arc ,
578- } ;
592+ use std:: { fs:: File , io:: Write , os:: unix:: io:: AsRawFd , sync:: Arc } ;
579593
580594 fn from_imp_client ( imp : ClientImp ) -> Client {
581595 Client {
@@ -629,7 +643,7 @@ mod test {
629643 #[ cfg( not( target_os = "linux" ) ) ]
630644 assert_eq ! (
631645 new_client_from_pipe( ) . 0 . try_acquire( ) . unwrap_err( ) . kind( ) ,
632- io:: ErrorKind :: Unsupported
646+ std :: io:: ErrorKind :: Unsupported
633647 ) ;
634648
635649 #[ cfg( target_os = "linux" ) ]
0 commit comments