@@ -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,52 @@ 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
79
if PIPE2_AVAILABLE . load ( Ordering :: SeqCst ) {
82
- match libc:: syscall ( libc:: SYS_pipe2 , pipes. as_mut_ptr ( ) , libc:: O_CLOEXEC ) {
83
- -1 => {
84
- let err = io:: Error :: last_os_error ( ) ;
85
- if err. raw_os_error ( ) == Some ( libc:: ENOSYS ) {
86
- PIPE2_AVAILABLE . store ( false , Ordering :: SeqCst ) ;
87
- } else {
88
- return Err ( err) ;
80
+ unsafe {
81
+ let mut pipes = [ 0 ; 2 ] ;
82
+ match libc:: syscall ( libc:: SYS_pipe2 , pipes. as_mut_ptr ( ) , libc:: O_CLOEXEC ) {
83
+ -1 => {
84
+ let err = io:: Error :: last_os_error ( ) ;
85
+ if err. raw_os_error ( ) == Some ( libc:: ENOSYS ) {
86
+ PIPE2_AVAILABLE . store ( false , Ordering :: SeqCst ) ;
87
+ } else {
88
+ return Err ( err) ;
89
+ }
90
+ }
91
+ _ => {
92
+ return Ok ( Client :: from_fds (
93
+ OwnedFd :: from_raw_fd ( pipes[ 0 ] ) ,
94
+ OwnedFd :: from_raw_fd ( pipes[ 1 ] ) ,
95
+ ) )
89
96
}
90
97
}
91
- _ => return Ok ( Client :: from_fds ( pipes[ 0 ] , pipes[ 1 ] ) ) ,
92
98
}
93
99
}
94
100
}
95
101
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 ] ) )
102
+ let ( read, write) = unsafe {
103
+ let mut pipes = [ 0 ; 2 ] ;
104
+ cvt ( libc:: pipe ( pipes. as_mut_ptr ( ) ) ) ?;
105
+ (
106
+ OwnedFd :: from_raw_fd ( pipes[ 0 ] ) ,
107
+ OwnedFd :: from_raw_fd ( pipes[ 1 ] ) ,
108
+ )
109
+ } ;
110
+ drop ( set_cloexec ( read. as_fd ( ) , true ) ) ;
111
+ drop ( set_cloexec ( write. as_fd ( ) , true ) ) ;
112
+ Ok ( Client :: from_fds ( read, write) )
100
113
}
101
114
102
115
pub ( crate ) unsafe fn open ( s : & str , check_pipe : bool ) -> Result < Client , FromEnvErrorInner > {
@@ -211,18 +224,21 @@ impl Client {
211
224
}
212
225
213
226
Ok ( Some ( Client {
214
- read : clone_fd_and_set_cloexec ( read) ?,
215
- write : clone_fd_and_set_cloexec ( write) ?,
227
+ read : clone_fd_and_set_cloexec ( BorrowedFd :: borrow_raw ( read) ) ?,
228
+ write : clone_fd_and_set_cloexec ( BorrowedFd :: borrow_raw ( write) ) ?,
216
229
creation_arg,
217
230
is_non_blocking : None ,
218
231
} ) )
219
232
}
220
233
221
- unsafe fn from_fds ( read : c_int , write : c_int ) -> Client {
234
+ fn from_fds ( read : OwnedFd , write : OwnedFd ) -> Client {
222
235
Client {
223
- read : File :: from_raw_fd ( read) ,
224
- write : File :: from_raw_fd ( write) ,
225
- creation_arg : ClientCreationArg :: Fds { read, write } ,
236
+ creation_arg : ClientCreationArg :: Fds {
237
+ read : read. as_raw_fd ( ) ,
238
+ write : write. as_raw_fd ( ) ,
239
+ } ,
240
+ read : read. into ( ) ,
241
+ write : write. into ( ) ,
226
242
is_non_blocking : None ,
227
243
}
228
244
}
@@ -304,7 +320,7 @@ impl Client {
304
320
305
321
if let Some ( is_non_blocking) = self . is_non_blocking . as_ref ( ) {
306
322
if !is_non_blocking. load ( Ordering :: Relaxed ) {
307
- set_nonblocking ( fifo. as_raw_fd ( ) , true ) ?;
323
+ set_nonblocking ( fifo. as_fd ( ) , true ) ?;
308
324
is_non_blocking. store ( true , Ordering :: Relaxed ) ;
309
325
}
310
326
} else {
@@ -357,24 +373,30 @@ impl Client {
357
373
Ok ( unsafe { len. assume_init ( ) } as usize )
358
374
}
359
375
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
- } ) ;
376
+ pub fn configure ( self : & Arc < Self > , cmd : & mut Command ) {
377
+ match self . creation_arg {
378
+ ClientCreationArg :: Fifo { .. } => {
379
+ // We `File::open`ed it when inheriting from environment,
380
+ // so no need to set cloexec for fifo.
381
+ }
382
+ ClientCreationArg :: Fds { read, write } => {
383
+ // Here we basically just want to say that in the child process
384
+ // we'll configure the read/write file descriptors to *not* be
385
+ // cloexec, so they're inherited across the exec and specified as
386
+ // integers through `string_arg` above.
387
+ unsafe {
388
+ // Keep a reference to the jobserver alive in the closure so that
389
+ // the pipe FDs aren't closed, otherwise `set_cloexec` might end up
390
+ // targetting a completely unrelated file descriptor.
391
+ let arc = self . clone ( ) ;
392
+ cmd. pre_exec ( move || {
393
+ let _ = & arc;
394
+ set_cloexec ( BorrowedFd :: borrow_raw ( read) , false ) ?;
395
+ set_cloexec ( BorrowedFd :: borrow_raw ( write) , false ) ?;
396
+ Ok ( ( ) )
397
+ } ) ;
398
+ }
399
+ }
378
400
}
379
401
}
380
402
}
@@ -515,34 +537,32 @@ unsafe fn fd_check(fd: c_int, check_pipe: bool) -> Result<(), FromEnvErrorInner>
515
537
}
516
538
}
517
539
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 ( )
540
+ fn clone_fd_and_set_cloexec ( fd : BorrowedFd < ' _ > ) -> Result < File , FromEnvErrorInner > {
541
+ fd. try_clone_to_owned ( )
522
542
. map ( File :: from)
523
- . map_err ( |err| FromEnvErrorInner :: CannotOpenFd ( fd, err) )
543
+ . map_err ( |err| FromEnvErrorInner :: CannotOpenFd ( fd. as_raw_fd ( ) , err) )
524
544
}
525
545
526
- fn set_cloexec ( fd : c_int , set : bool ) -> io:: Result < ( ) > {
546
+ fn set_cloexec ( fd : BorrowedFd < ' _ > , set : bool ) -> io:: Result < ( ) > {
527
547
unsafe {
528
- let previous = cvt ( libc:: fcntl ( fd, libc:: F_GETFD ) ) ?;
548
+ let previous = cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_GETFD ) ) ?;
529
549
let new = if set {
530
550
previous | libc:: FD_CLOEXEC
531
551
} else {
532
552
previous & !libc:: FD_CLOEXEC
533
553
} ;
534
554
if new != previous {
535
- cvt ( libc:: fcntl ( fd, libc:: F_SETFD , new) ) ?;
555
+ cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_SETFD , new) ) ?;
536
556
}
537
557
Ok ( ( ) )
538
558
}
539
559
}
540
560
541
- fn set_nonblocking ( fd : c_int , set : bool ) -> io:: Result < ( ) > {
561
+ fn set_nonblocking ( fd : BorrowedFd < ' _ > , set : bool ) -> io:: Result < ( ) > {
542
562
let status_flag = if set { libc:: O_NONBLOCK } else { 0 } ;
543
563
544
564
unsafe {
545
- cvt ( libc:: fcntl ( fd, libc:: F_SETFL , status_flag) ) ?;
565
+ cvt ( libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_SETFL , status_flag) ) ?;
546
566
}
547
567
548
568
Ok ( ( ) )
0 commit comments