@@ -6,7 +6,7 @@ use std::io::{self, Read, Write};
6
6
use std:: mem;
7
7
use std:: mem:: MaybeUninit ;
8
8
use std:: os:: unix:: prelude:: * ;
9
- use std:: path:: { Path , PathBuf } ;
9
+ use std:: path:: Path ;
10
10
use std:: process:: Command ;
11
11
use std:: ptr;
12
12
use std:: sync:: {
@@ -17,17 +17,15 @@ use std::thread::{self, Builder, JoinHandle};
17
17
use std:: time:: Duration ;
18
18
19
19
#[ derive( Debug ) ]
20
- pub enum Client {
21
- /// `--jobserver-auth=R,W`
22
- Pipe { read : File , write : File } ,
23
- /// `--jobserver-auth=fifo:PATH`
24
- Fifo {
25
- file : File ,
26
- path : PathBuf ,
27
- /// it can only go from false -> true but not the other way around, since that
28
- /// could cause a race condition.
29
- is_non_blocking : AtomicBool ,
30
- } ,
20
+ pub struct Client {
21
+ read : File ,
22
+ write : Option < File > ,
23
+ /// If path is not None, then a fifo jobserver is created.
24
+ path : Option < Box < Path > > ,
25
+ supports_non_blocking : bool ,
26
+ /// it can only go from false -> true but not the other way around, since that
27
+ /// could cause a race condition.
28
+ is_non_blocking : AtomicBool ,
31
29
}
32
30
33
31
#[ derive( Debug ) ]
@@ -117,9 +115,11 @@ impl Client {
117
115
. open ( path)
118
116
. map_err ( |err| FromEnvErrorInner :: CannotOpenPath ( path_str. to_string ( ) , err) ) ?;
119
117
120
- Ok ( Some ( Client :: Fifo {
121
- file,
122
- path : path. into ( ) ,
118
+ Ok ( Some ( Client {
119
+ read : file,
120
+ write : None ,
121
+ path : Some ( path. into ( ) ) ,
122
+ supports_non_blocking : true ,
123
123
is_non_blocking : AtomicBool :: new ( false ) ,
124
124
} ) )
125
125
}
@@ -174,41 +174,42 @@ impl Client {
174
174
//
175
175
// I tested this on macOS 14 and Linux 6.5.13
176
176
#[ cfg( target_os = "linux" ) ]
177
- if let Ok ( Some ( jobserver) ) =
177
+ if let Ok ( Some ( mut jobserver) ) =
178
178
Self :: from_fifo ( & format ! ( "fifo:/dev/fd/{}" , read. as_raw_fd( ) ) )
179
179
{
180
+ jobserver. path . take ( ) ;
180
181
return Ok ( Some ( jobserver) ) ;
181
182
}
182
183
}
183
184
}
184
185
185
- Ok ( Some ( Client :: Pipe {
186
+ Ok ( Some ( Client {
186
187
read : clone_fd_and_set_cloexec ( read) ?,
187
- write : clone_fd_and_set_cloexec ( write) ?,
188
+ write : Some ( clone_fd_and_set_cloexec ( write) ?) ,
189
+ path : None ,
190
+ supports_non_blocking : false ,
191
+ is_non_blocking : AtomicBool :: new ( false ) ,
188
192
} ) )
189
193
}
190
194
191
195
unsafe fn from_fds ( read : c_int , write : c_int ) -> Client {
192
- Client :: Pipe {
196
+ Client {
193
197
read : File :: from_raw_fd ( read) ,
194
- write : File :: from_raw_fd ( write) ,
198
+ write : Some ( File :: from_raw_fd ( write) ) ,
199
+ path : None ,
200
+ supports_non_blocking : false ,
201
+ is_non_blocking : AtomicBool :: new ( false ) ,
195
202
}
196
203
}
197
204
198
205
/// Gets the read end of our jobserver client.
199
206
fn read ( & self ) -> & File {
200
- match self {
201
- Client :: Pipe { read, .. } => read,
202
- Client :: Fifo { file, .. } => file,
203
- }
207
+ & self . read
204
208
}
205
209
206
210
/// Gets the write end of our jobserver client.
207
211
fn write ( & self ) -> & File {
208
- match self {
209
- Client :: Pipe { write, .. } => write,
210
- Client :: Fifo { file, .. } => file,
211
- }
212
+ self . write . as_ref ( ) . unwrap_or ( & self . read )
212
213
}
213
214
214
215
pub fn acquire ( & self ) -> io:: Result < Acquired > {
@@ -285,18 +286,15 @@ impl Client {
285
286
pub fn try_acquire ( & self ) -> io:: Result < Option < Acquired > > {
286
287
let mut buf = [ 0 ] ;
287
288
288
- let ( mut fifo, is_non_blocking) = match self {
289
- Self :: Fifo {
290
- file,
291
- is_non_blocking,
292
- ..
293
- } => ( file, is_non_blocking) ,
294
- _ => return Err ( io:: ErrorKind :: Unsupported . into ( ) ) ,
295
- } ;
289
+ if !self . supports_non_blocking {
290
+ return Err ( io:: ErrorKind :: Unsupported . into ( ) ) ;
291
+ }
292
+
293
+ let mut fifo = self . read ( ) ;
296
294
297
- if !is_non_blocking. load ( Ordering :: Relaxed ) {
295
+ if !self . is_non_blocking . load ( Ordering :: Relaxed ) {
298
296
set_nonblocking ( fifo. as_raw_fd ( ) , true ) ?;
299
- is_non_blocking. store ( true , Ordering :: Relaxed ) ;
297
+ self . is_non_blocking . store ( true , Ordering :: Relaxed ) ;
300
298
}
301
299
302
300
loop {
@@ -333,10 +331,10 @@ impl Client {
333
331
}
334
332
335
333
pub fn string_arg ( & self ) -> String {
336
- match self {
337
- Client :: Pipe { read , write } => format ! ( "{},{}" , read . as_raw_fd ( ) , write . as_raw_fd ( ) ) ,
338
- Client :: Fifo { path, .. } => format ! ( "fifo:{}" , path. to_str ( ) . unwrap ( ) ) ,
339
- }
334
+ self . path
335
+ . as_deref ( )
336
+ . map ( | path| format ! ( "fifo:{}" , path. display ( ) ) )
337
+ . unwrap_or_else ( || format ! ( "{},{}" , self . read ( ) . as_raw_fd ( ) , self . write ( ) . as_raw_fd ( ) ) )
340
338
}
341
339
342
340
pub fn available ( & self ) -> io:: Result < usize > {
@@ -346,12 +344,11 @@ impl Client {
346
344
}
347
345
348
346
pub fn configure ( & self , cmd : & mut Command ) {
349
- match self {
347
+ if self . path . is_some ( ) {
350
348
// We `File::open`ed it when inheriting from environment,
351
349
// so no need to set cloexec for fifo.
352
- Client :: Fifo { .. } => return ,
353
- Client :: Pipe { .. } => { }
354
- } ;
350
+ return ;
351
+ }
355
352
// Here we basically just want to say that in the child process
356
353
// we'll configure the read/write file descriptors to *not* be
357
354
// cloexec, so they're inherited across the exec and specified as
0 commit comments