@@ -47,15 +47,15 @@ pub struct Acquired {
47
47
48
48
impl Client {
49
49
pub fn new ( mut limit : usize ) -> io:: Result < Client > {
50
- let client = unsafe { Client :: mk ( ) ? } ;
50
+ let client = Client :: mk ( ) ?;
51
51
52
52
// I don't think the character written here matters, but I could be
53
53
// wrong!
54
54
const BUFFER : [ u8 ; 128 ] = [ b'|' ; 128 ] ;
55
55
56
56
let mut write = & client. write ;
57
57
58
- set_nonblocking ( write. as_raw_fd ( ) , true ) ?;
58
+ set_nonblocking ( write. as_fd ( ) , true ) ?;
59
59
60
60
while limit > 0 {
61
61
let n = limit. min ( BUFFER . len ( ) ) ;
@@ -64,39 +64,51 @@ impl Client {
64
64
limit -= n;
65
65
}
66
66
67
- set_nonblocking ( write. as_raw_fd ( ) , false ) ?;
67
+ set_nonblocking ( write. as_fd ( ) , false ) ?;
68
68
69
69
Ok ( client)
70
70
}
71
71
72
- unsafe fn mk ( ) -> io:: Result < Client > {
73
- let mut pipes = [ 0 ; 2 ] ;
74
-
72
+ fn mk ( ) -> io:: Result < Client > {
75
73
// Attempt atomically-create-with-cloexec if we can on Linux,
76
74
// detected by using the `syscall` function in `libc` to try to work
77
75
// with as many kernels/glibc implementations as possible.
78
76
#[ cfg( target_os = "linux" ) ]
79
77
{
80
78
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
+ {
83
83
-1 => {
84
84
let err = io:: Error :: last_os_error ( ) ;
85
85
if err. raw_os_error ( ) == Some ( libc:: ENOSYS ) {
86
- PIPE2_AVAILABLE . store ( false , Ordering :: SeqCst ) ;
86
+ PIPE2_AVAILABLE . store ( false , Ordering :: Relaxed ) ;
87
87
} else {
88
88
return Err ( err) ;
89
89
}
90
90
}
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
+ } ,
92
97
}
93
98
}
94
99
}
95
100
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) )
100
112
}
101
113
102
114
pub ( crate ) unsafe fn open ( s : & str , check_pipe : bool ) -> Result < Client , FromEnvErrorInner > {
@@ -211,18 +223,21 @@ impl Client {
211
223
}
212
224
213
225
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) ) ?,
216
228
creation_arg,
217
229
is_non_blocking : None ,
218
230
} ) )
219
231
}
220
232
221
- unsafe fn from_fds ( read : c_int , write : c_int ) -> Client {
233
+ fn from_fds ( read : OwnedFd , write : OwnedFd ) -> Client {
222
234
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 ( ) ,
226
241
is_non_blocking : None ,
227
242
}
228
243
}
@@ -304,7 +319,7 @@ impl Client {
304
319
305
320
if let Some ( is_non_blocking) = self . is_non_blocking . as_ref ( ) {
306
321
if !is_non_blocking. load ( Ordering :: Relaxed ) {
307
- set_nonblocking ( fifo. as_raw_fd ( ) , true ) ?;
322
+ set_nonblocking ( fifo. as_fd ( ) , true ) ?;
308
323
is_non_blocking. store ( true , Ordering :: Relaxed ) ;
309
324
}
310
325
} else {
@@ -357,24 +372,30 @@ impl Client {
357
372
Ok ( unsafe { len. assume_init ( ) } as usize )
358
373
}
359
374
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
+ }
378
399
}
379
400
}
380
401
}
@@ -515,34 +536,32 @@ unsafe fn fd_check(fd: c_int, check_pipe: bool) -> Result<(), FromEnvErrorInner>
515
536
}
516
537
}
517
538
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 ( )
522
541
. map ( File :: from)
523
- . map_err ( |err| FromEnvErrorInner :: CannotOpenFd ( fd, err) )
542
+ . map_err ( |err| FromEnvErrorInner :: CannotOpenFd ( fd. as_raw_fd ( ) , err) )
524
543
}
525
544
526
- fn set_cloexec ( fd : c_int , set : bool ) -> io:: Result < ( ) > {
545
+ fn set_cloexec ( fd : BorrowedFd < ' _ > , set : bool ) -> io:: Result < ( ) > {
527
546
unsafe {
528
- let previous = cvt ( libc:: fcntl ( fd, libc:: F_GETFD ) ) ?;
547
+ let previous = cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_GETFD ) ) ?;
529
548
let new = if set {
530
549
previous | libc:: FD_CLOEXEC
531
550
} else {
532
551
previous & !libc:: FD_CLOEXEC
533
552
} ;
534
553
if new != previous {
535
- cvt ( libc:: fcntl ( fd, libc:: F_SETFD , new) ) ?;
554
+ cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_SETFD , new) ) ?;
536
555
}
537
556
Ok ( ( ) )
538
557
}
539
558
}
540
559
541
- fn set_nonblocking ( fd : c_int , set : bool ) -> io:: Result < ( ) > {
560
+ fn set_nonblocking ( fd : BorrowedFd < ' _ > , set : bool ) -> io:: Result < ( ) > {
542
561
let status_flag = if set { libc:: O_NONBLOCK } else { 0 } ;
543
562
544
563
unsafe {
545
- cvt ( libc:: fcntl ( fd, libc:: F_SETFL , status_flag) ) ?;
564
+ cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_SETFL , status_flag) ) ?;
546
565
}
547
566
548
567
Ok ( ( ) )
@@ -570,12 +589,7 @@ mod test {
570
589
571
590
use crate :: { test:: run_named_fifo_try_acquire_tests, Client } ;
572
591
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 } ;
579
593
580
594
fn from_imp_client ( imp : ClientImp ) -> Client {
581
595
Client {
0 commit comments