@@ -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  { 
0 commit comments