@@ -24,6 +24,7 @@ impl Command {
24
24
-> io:: Result < ( Process , StdioPipes ) > {
25
25
use sys;
26
26
27
+
27
28
const CLOEXEC_MSG_FOOTER : & ' static [ u8 ] = b"NOEX" ;
28
29
29
30
let envp = self . capture_env ( ) ;
@@ -34,6 +35,11 @@ impl Command {
34
35
}
35
36
36
37
let ( ours, theirs) = self . setup_io ( default, needs_stdin) ?;
38
+
39
+ if let Some ( ret) = self . posix_spawn ( & theirs, envp. as_ref ( ) ) ? {
40
+ return Ok ( ( ret, ours) )
41
+ }
42
+
37
43
let ( input, output) = sys:: pipe:: anon_pipe ( ) ?;
38
44
39
45
let pid = unsafe {
@@ -229,6 +235,102 @@ impl Command {
229
235
libc:: execvp ( self . get_argv ( ) [ 0 ] , self . get_argv ( ) . as_ptr ( ) ) ;
230
236
io:: Error :: last_os_error ( )
231
237
}
238
+
239
+ #[ cfg( not( any( target_os = "linux" , target_os = "macos" ) ) ) ]
240
+ fn posix_spawn ( & mut self , stdio : & ChildPipes , envp : Option < & CStringArray > )
241
+ -> io:: Result < Option < Process > >
242
+ {
243
+ Ok ( None )
244
+ }
245
+
246
+ #[ cfg( any( target_os = "linux" , target_os = "macos" ) ) ]
247
+ fn posix_spawn ( & mut self , stdio : & ChildPipes , envp : Option < & CStringArray > )
248
+ -> io:: Result < Option < Process > >
249
+ {
250
+ use mem;
251
+ use sys;
252
+
253
+ if self . get_cwd ( ) . is_some ( ) ||
254
+ self . get_gid ( ) . is_some ( ) ||
255
+ self . get_uid ( ) . is_some ( ) ||
256
+ self . get_closures ( ) . len ( ) != 0 {
257
+ return Ok ( None )
258
+ }
259
+
260
+ let mut p = Process { pid : 0 , status : None } ;
261
+
262
+ struct PosixSpawnFileActions ( libc:: posix_spawn_file_actions_t ) ;
263
+
264
+ impl Drop for PosixSpawnFileActions {
265
+ fn drop ( & mut self ) {
266
+ unsafe {
267
+ libc:: posix_spawn_file_actions_destroy ( & mut self . 0 ) ;
268
+ }
269
+ }
270
+ }
271
+
272
+ struct PosixSpawnattr ( libc:: posix_spawnattr_t ) ;
273
+
274
+ impl Drop for PosixSpawnattr {
275
+ fn drop ( & mut self ) {
276
+ unsafe {
277
+ libc:: posix_spawnattr_destroy ( & mut self . 0 ) ;
278
+ }
279
+ }
280
+ }
281
+
282
+ unsafe {
283
+ let mut file_actions = PosixSpawnFileActions ( mem:: zeroed ( ) ) ;
284
+ let mut attrs = PosixSpawnattr ( mem:: zeroed ( ) ) ;
285
+
286
+ libc:: posix_spawnattr_init ( & mut attrs. 0 ) ;
287
+ libc:: posix_spawn_file_actions_init ( & mut file_actions. 0 ) ;
288
+
289
+ if let Some ( fd) = stdio. stdin . fd ( ) {
290
+ cvt ( libc:: posix_spawn_file_actions_adddup2 ( & mut file_actions. 0 ,
291
+ fd,
292
+ libc:: STDIN_FILENO ) ) ?;
293
+ }
294
+ if let Some ( fd) = stdio. stdout . fd ( ) {
295
+ cvt ( libc:: posix_spawn_file_actions_adddup2 ( & mut file_actions. 0 ,
296
+ fd,
297
+ libc:: STDOUT_FILENO ) ) ?;
298
+ }
299
+ if let Some ( fd) = stdio. stderr . fd ( ) {
300
+ cvt ( libc:: posix_spawn_file_actions_adddup2 ( & mut file_actions. 0 ,
301
+ fd,
302
+ libc:: STDERR_FILENO ) ) ?;
303
+ }
304
+
305
+ let mut set: libc:: sigset_t = mem:: zeroed ( ) ;
306
+ cvt ( libc:: sigemptyset ( & mut set) ) ?;
307
+ cvt ( libc:: posix_spawnattr_setsigmask ( & mut attrs. 0 ,
308
+ & set) ) ?;
309
+ cvt ( libc:: sigaddset ( & mut set, libc:: SIGPIPE ) ) ?;
310
+ cvt ( libc:: posix_spawnattr_setsigdefault ( & mut attrs. 0 ,
311
+ & set) ) ?;
312
+
313
+ let flags = libc:: POSIX_SPAWN_SETSIGDEF |
314
+ libc:: POSIX_SPAWN_SETSIGMASK ;
315
+ cvt ( libc:: posix_spawnattr_setflags ( & mut attrs. 0 , flags as _ ) ) ?;
316
+
317
+ let envp = envp. map ( |c| c. as_ptr ( ) )
318
+ . unwrap_or ( sys:: os:: environ ( ) as * const _ ) ;
319
+ let ret = libc:: posix_spawnp (
320
+ & mut p. pid ,
321
+ self . get_argv ( ) [ 0 ] ,
322
+ & file_actions. 0 ,
323
+ & attrs. 0 ,
324
+ self . get_argv ( ) . as_ptr ( ) as * const _ ,
325
+ envp as * const _ ,
326
+ ) ;
327
+ if ret == 0 {
328
+ Ok ( Some ( p) )
329
+ } else {
330
+ Err ( io:: Error :: last_os_error ( ) )
331
+ }
332
+ }
333
+ }
232
334
}
233
335
234
336
////////////////////////////////////////////////////////////////////////////////
0 commit comments