@@ -15,14 +15,19 @@ use libc::c_int;
15
15
16
16
use crate :: Command ;
17
17
18
+ #[ derive( Debug ) ]
19
+ enum ClientCreationArg {
20
+ Fds { read : c_int , write : c_int } ,
21
+ Fifo ( Box < Path > ) ,
22
+ }
23
+
18
24
#[ derive( Debug ) ]
19
25
pub struct Client {
20
26
/// This fd is set to be nonblocking
21
27
read : File ,
22
28
/// This fd is set to be blocking
23
29
write : File ,
24
- /// Path to the named fifo if any
25
- path : Option < Box < Path > > ,
30
+ creation_arg : ClientCreationArg ,
26
31
/// If the Client owns the fifo, then we should remove it on drop.
27
32
owns_fifo : bool ,
28
33
}
@@ -78,7 +83,7 @@ impl Client {
78
83
let client = Self {
79
84
read : file. try_clone ( ) ?,
80
85
write : file,
81
- path : Some ( name. into_boxed_path ( ) ) ,
86
+ creation_arg : ClientCreationArg :: Fifo ( name. into_boxed_path ( ) ) ,
82
87
owns_fifo : true ,
83
88
} ;
84
89
@@ -131,13 +136,13 @@ impl Client {
131
136
132
137
/// `--jobserver-auth=fifo:PATH`
133
138
fn from_fifo ( path : & Path ) -> Option < Self > {
134
- let file = open_file_rw ( path) . ok ( ) ?;
139
+ let read = open_file_rw ( path) . ok ( ) ?;
135
140
136
- if is_pipe ( & file ) ? {
141
+ if is_pipe ( & read ) ? {
137
142
Some ( Self {
138
- read : file . try_clone ( ) . ok ( ) ? ,
139
- write : file ,
140
- path : Some ( path. into ( ) ) ,
143
+ read,
144
+ write : open_file_rw ( path ) . ok ( ) ? ,
145
+ creation_arg : ClientCreationArg :: Fifo ( path. into ( ) ) ,
141
146
owns_fifo : false ,
142
147
} )
143
148
} else {
@@ -152,6 +157,8 @@ impl Client {
152
157
let read = read. parse ( ) . ok ( ) ?;
153
158
let write = write. parse ( ) . ok ( ) ?;
154
159
160
+ let creation_arg = ClientCreationArg :: Fds { read, write } ;
161
+
155
162
let read = ManuallyDrop :: new ( File :: from_raw_fd ( read) ) ;
156
163
let write = ManuallyDrop :: new ( File :: from_raw_fd ( write) ) ;
157
164
@@ -183,6 +190,19 @@ impl Client {
183
190
//
184
191
// I tested this on macOS 14 and Linux 6.5.13
185
192
#[ cfg( target_os = "linux" ) ]
193
+ if let ( Ok ( read) , Ok ( write) ) = (
194
+ File :: open ( format ! ( "/dev/fd/{}" , read) ) ,
195
+ OpenOptions :: new ( )
196
+ . write ( true )
197
+ . open ( format ! ( "/dev/fd/{}" , write) ) ,
198
+ ) {
199
+ return Ok ( Some ( Client {
200
+ read,
201
+ write,
202
+ creation_arg,
203
+ owns_fifo : false ,
204
+ } ) ) ;
205
+ }
186
206
if let Some ( jobserver) =
187
207
Self :: from_fifo ( Path :: new ( & format ! ( "/dev/fd/{}" , read. as_raw_fd( ) ) ) )
188
208
{
@@ -195,7 +215,7 @@ impl Client {
195
215
Some ( Self {
196
216
read,
197
217
write,
198
- path : None ,
218
+ creation_arg ,
199
219
owns_fifo : false ,
200
220
} )
201
221
}
@@ -207,7 +227,7 @@ impl Client {
207
227
Self {
208
228
read : File :: from_raw_fd ( read) ,
209
229
write : File :: from_raw_fd ( write) ,
210
- path : None ,
230
+ creation_arg : ClientCreationArg :: Fds { read , write } ,
211
231
owns_fifo : false ,
212
232
}
213
233
}
@@ -268,15 +288,18 @@ impl Client {
268
288
}
269
289
270
290
pub fn string_arg ( & self ) -> Cow < ' _ , str > {
271
- Cow :: Owned ( format ! (
272
- "{},{}" ,
273
- self . read. as_raw_fd( ) ,
274
- self . write. as_raw_fd( )
275
- ) )
291
+ Cow :: Owned ( match & self . creation_arg {
292
+ ClientCreationArg :: Fifo ( path) => format ! ( "fifo:{}" , path. display( ) ) ,
293
+ ClientCreationArg :: Fds { read, write } => format ! ( "{},{}" , read, write) ,
294
+ } )
276
295
}
277
296
278
297
pub fn get_fifo ( & self ) -> Option < & Path > {
279
- self . path . as_deref ( )
298
+ if let ClientCreationArg :: Fifo ( path) = & self . creation_arg {
299
+ Some ( path)
300
+ } else {
301
+ None
302
+ }
280
303
}
281
304
282
305
pub fn pre_run < Cmd > ( & self , cmd : & mut Cmd )
@@ -309,7 +332,7 @@ impl Client {
309
332
}
310
333
311
334
pub fn is_try_acquire_safe ( & self ) -> bool {
312
- self . path . is_some ( )
335
+ self . get_fifo ( ) . is_some ( )
313
336
}
314
337
315
338
pub fn set_nonblocking ( & self ) -> io:: Result < ( ) > {
@@ -325,7 +348,7 @@ impl Client {
325
348
326
349
impl Drop for Client {
327
350
fn drop ( & mut self ) {
328
- if let Some ( path) = & self . path {
351
+ if let Some ( path) = self . get_fifo ( ) {
329
352
if self . owns_fifo {
330
353
fs:: remove_file ( path) . ok ( ) ;
331
354
}
0 commit comments