11
11
//! Working with processes.
12
12
13
13
#![ stable( feature = "process" , since = "1.0.0" ) ]
14
- #![ allow( non_upper_case_globals) ]
15
14
16
15
use prelude:: v1:: * ;
17
16
use io:: prelude:: * ;
18
17
19
18
use ffi:: OsStr ;
20
19
use fmt;
21
- use io:: { self , Error , ErrorKind } ;
22
- use path;
20
+ use io;
21
+ use path:: Path ;
23
22
use str;
24
- use sys:: pipe:: { self , AnonPipe } ;
23
+ use sys:: pipe:: AnonPipe ;
25
24
use sys:: process as imp;
26
25
use sys_common:: { AsInner , AsInnerMut , FromInner , IntoInner } ;
27
26
use thread:: { self , JoinHandle } ;
@@ -61,9 +60,6 @@ use thread::{self, JoinHandle};
61
60
pub struct Child {
62
61
handle : imp:: Process ,
63
62
64
- /// None until wait() or wait_with_output() is called.
65
- status : Option < imp:: ExitStatus > ,
66
-
67
63
/// The handle for writing to the child's stdin, if it has been captured
68
64
#[ stable( feature = "process" , since = "1.0.0" ) ]
69
65
pub stdin : Option < ChildStdin > ,
@@ -81,6 +77,17 @@ impl AsInner<imp::Process> for Child {
81
77
fn as_inner ( & self ) -> & imp:: Process { & self . handle }
82
78
}
83
79
80
+ impl FromInner < ( imp:: Process , imp:: StdioPipes ) > for Child {
81
+ fn from_inner ( ( handle, io) : ( imp:: Process , imp:: StdioPipes ) ) -> Child {
82
+ Child {
83
+ handle : handle,
84
+ stdin : io. stdin . map ( ChildStdin :: from_inner) ,
85
+ stdout : io. stdout . map ( ChildStdout :: from_inner) ,
86
+ stderr : io. stderr . map ( ChildStderr :: from_inner) ,
87
+ }
88
+ }
89
+ }
90
+
84
91
impl IntoInner < imp:: Process > for Child {
85
92
fn into_inner ( self ) -> imp:: Process { self . handle }
86
93
}
@@ -110,6 +117,12 @@ impl IntoInner<AnonPipe> for ChildStdin {
110
117
fn into_inner ( self ) -> AnonPipe { self . inner }
111
118
}
112
119
120
+ impl FromInner < AnonPipe > for ChildStdin {
121
+ fn from_inner ( pipe : AnonPipe ) -> ChildStdin {
122
+ ChildStdin { inner : pipe }
123
+ }
124
+ }
125
+
113
126
/// A handle to a child process's stdout
114
127
#[ stable( feature = "process" , since = "1.0.0" ) ]
115
128
pub struct ChildStdout {
@@ -131,6 +144,12 @@ impl IntoInner<AnonPipe> for ChildStdout {
131
144
fn into_inner ( self ) -> AnonPipe { self . inner }
132
145
}
133
146
147
+ impl FromInner < AnonPipe > for ChildStdout {
148
+ fn from_inner ( pipe : AnonPipe ) -> ChildStdout {
149
+ ChildStdout { inner : pipe }
150
+ }
151
+ }
152
+
134
153
/// A handle to a child process's stderr
135
154
#[ stable( feature = "process" , since = "1.0.0" ) ]
136
155
pub struct ChildStderr {
@@ -152,6 +171,12 @@ impl IntoInner<AnonPipe> for ChildStderr {
152
171
fn into_inner ( self ) -> AnonPipe { self . inner }
153
172
}
154
173
174
+ impl FromInner < AnonPipe > for ChildStderr {
175
+ fn from_inner ( pipe : AnonPipe ) -> ChildStderr {
176
+ ChildStderr { inner : pipe }
177
+ }
178
+ }
179
+
155
180
/// The `Command` type acts as a process builder, providing fine-grained control
156
181
/// over how a new process should be spawned. A default configuration can be
157
182
/// generated using `Command::new(program)`, where `program` gives a path to the
@@ -171,11 +196,6 @@ impl IntoInner<AnonPipe> for ChildStderr {
171
196
#[ stable( feature = "process" , since = "1.0.0" ) ]
172
197
pub struct Command {
173
198
inner : imp:: Command ,
174
-
175
- // Details explained in the builder methods
176
- stdin : Option < Stdio > ,
177
- stdout : Option < Stdio > ,
178
- stderr : Option < Stdio > ,
179
199
}
180
200
181
201
impl Command {
@@ -191,12 +211,7 @@ impl Command {
191
211
/// otherwise configure the process.
192
212
#[ stable( feature = "process" , since = "1.0.0" ) ]
193
213
pub fn new < S : AsRef < OsStr > > ( program : S ) -> Command {
194
- Command {
195
- inner : imp:: Command :: new ( program. as_ref ( ) ) ,
196
- stdin : None ,
197
- stdout : None ,
198
- stderr : None ,
199
- }
214
+ Command { inner : imp:: Command :: new ( program. as_ref ( ) ) }
200
215
}
201
216
202
217
/// Add an argument to pass to the program.
@@ -209,7 +224,9 @@ impl Command {
209
224
/// Add multiple arguments to pass to the program.
210
225
#[ stable( feature = "process" , since = "1.0.0" ) ]
211
226
pub fn args < S : AsRef < OsStr > > ( & mut self , args : & [ S ] ) -> & mut Command {
212
- self . inner . args ( args. iter ( ) . map ( AsRef :: as_ref) ) ;
227
+ for arg in args {
228
+ self . arg ( arg. as_ref ( ) ) ;
229
+ }
213
230
self
214
231
}
215
232
@@ -241,65 +258,38 @@ impl Command {
241
258
242
259
/// Sets the working directory for the child process.
243
260
#[ stable( feature = "process" , since = "1.0.0" ) ]
244
- pub fn current_dir < P : AsRef < path :: Path > > ( & mut self , dir : P ) -> & mut Command {
261
+ pub fn current_dir < P : AsRef < Path > > ( & mut self , dir : P ) -> & mut Command {
245
262
self . inner . cwd ( dir. as_ref ( ) . as_ref ( ) ) ;
246
263
self
247
264
}
248
265
249
266
/// Configuration for the child process's stdin handle (file descriptor 0).
250
267
#[ stable( feature = "process" , since = "1.0.0" ) ]
251
268
pub fn stdin ( & mut self , cfg : Stdio ) -> & mut Command {
252
- self . stdin = Some ( cfg) ;
269
+ self . inner . stdin ( cfg. 0 ) ;
253
270
self
254
271
}
255
272
256
273
/// Configuration for the child process's stdout handle (file descriptor 1).
257
274
#[ stable( feature = "process" , since = "1.0.0" ) ]
258
275
pub fn stdout ( & mut self , cfg : Stdio ) -> & mut Command {
259
- self . stdout = Some ( cfg) ;
276
+ self . inner . stdout ( cfg. 0 ) ;
260
277
self
261
278
}
262
279
263
280
/// Configuration for the child process's stderr handle (file descriptor 2).
264
281
#[ stable( feature = "process" , since = "1.0.0" ) ]
265
282
pub fn stderr ( & mut self , cfg : Stdio ) -> & mut Command {
266
- self . stderr = Some ( cfg) ;
283
+ self . inner . stderr ( cfg. 0 ) ;
267
284
self
268
285
}
269
286
270
- fn spawn_inner ( & self , default_io : StdioImp ) -> io:: Result < Child > {
271
- let default_io = Stdio ( default_io) ;
272
-
273
- // See comment on `setup_io` for what `_drop_later` is.
274
- let ( their_stdin, our_stdin, _drop_later) = try!(
275
- setup_io ( self . stdin . as_ref ( ) . unwrap_or ( & default_io) , true )
276
- ) ;
277
- let ( their_stdout, our_stdout, _drop_later) = try!(
278
- setup_io ( self . stdout . as_ref ( ) . unwrap_or ( & default_io) , false )
279
- ) ;
280
- let ( their_stderr, our_stderr, _drop_later) = try!(
281
- setup_io ( self . stderr . as_ref ( ) . unwrap_or ( & default_io) , false )
282
- ) ;
283
-
284
- match imp:: Process :: spawn ( & self . inner , their_stdin, their_stdout,
285
- their_stderr) {
286
- Err ( e) => Err ( e) ,
287
- Ok ( handle) => Ok ( Child {
288
- handle : handle,
289
- status : None ,
290
- stdin : our_stdin. map ( |fd| ChildStdin { inner : fd } ) ,
291
- stdout : our_stdout. map ( |fd| ChildStdout { inner : fd } ) ,
292
- stderr : our_stderr. map ( |fd| ChildStderr { inner : fd } ) ,
293
- } )
294
- }
295
- }
296
-
297
287
/// Executes the command as a child process, returning a handle to it.
298
288
///
299
289
/// By default, stdin, stdout and stderr are inherited from the parent.
300
290
#[ stable( feature = "process" , since = "1.0.0" ) ]
301
291
pub fn spawn ( & mut self ) -> io:: Result < Child > {
302
- self . spawn_inner ( StdioImp :: Inherit )
292
+ self . inner . spawn ( imp :: Stdio :: Inherit ) . map ( Child :: from_inner )
303
293
}
304
294
305
295
/// Executes the command as a child process, waiting for it to finish and
@@ -322,7 +312,8 @@ impl Command {
322
312
/// ```
323
313
#[ stable( feature = "process" , since = "1.0.0" ) ]
324
314
pub fn output ( & mut self ) -> io:: Result < Output > {
325
- self . spawn_inner ( StdioImp :: MakePipe ) . and_then ( |p| p. wait_with_output ( ) )
315
+ self . inner . spawn ( imp:: Stdio :: MakePipe ) . map ( Child :: from_inner)
316
+ . and_then ( |p| p. wait_with_output ( ) )
326
317
}
327
318
328
319
/// Executes a command as a child process, waiting for it to finish and
@@ -365,33 +356,6 @@ impl AsInnerMut<imp::Command> for Command {
365
356
fn as_inner_mut ( & mut self ) -> & mut imp:: Command { & mut self . inner }
366
357
}
367
358
368
- // Takes a `Stdio` configuration (this module) and whether the to-be-owned
369
- // handle will be readable.
370
- //
371
- // Returns a triple of (stdio to spawn with, stdio to store, stdio to drop). The
372
- // stdio to spawn with is passed down to the `sys` module and indicates how the
373
- // stdio stream should be set up. The "stdio to store" is an object which
374
- // should be returned in the `Child` that makes its way out. The "stdio to drop"
375
- // represents the raw value of "stdio to spawn with", but is the owned variant
376
- // for it. This needs to be dropped after the child spawns
377
- fn setup_io ( io : & Stdio , readable : bool )
378
- -> io:: Result < ( imp:: Stdio , Option < AnonPipe > , Option < AnonPipe > ) >
379
- {
380
- Ok ( match io. 0 {
381
- StdioImp :: MakePipe => {
382
- let ( reader, writer) = try!( pipe:: anon_pipe ( ) ) ;
383
- if readable {
384
- ( imp:: Stdio :: Raw ( reader. raw ( ) ) , Some ( writer) , Some ( reader) )
385
- } else {
386
- ( imp:: Stdio :: Raw ( writer. raw ( ) ) , Some ( reader) , Some ( writer) )
387
- }
388
- }
389
- StdioImp :: Raw ( ref owned) => ( imp:: Stdio :: Raw ( owned. raw ( ) ) , None , None ) ,
390
- StdioImp :: Inherit => ( imp:: Stdio :: Inherit , None , None ) ,
391
- StdioImp :: None => ( imp:: Stdio :: None , None , None ) ,
392
- } )
393
- }
394
-
395
359
/// The output of a finished process.
396
360
#[ derive( PartialEq , Eq , Clone ) ]
397
361
#[ stable( feature = "process" , since = "1.0.0" ) ]
@@ -435,34 +399,26 @@ impl fmt::Debug for Output {
435
399
436
400
/// Describes what to do with a standard I/O stream for a child process.
437
401
#[ stable( feature = "process" , since = "1.0.0" ) ]
438
- pub struct Stdio ( StdioImp ) ;
439
-
440
- // The internal enum for stdio setup; see below for descriptions.
441
- enum StdioImp {
442
- MakePipe ,
443
- Raw ( imp:: RawStdio ) ,
444
- Inherit ,
445
- None ,
446
- }
402
+ pub struct Stdio ( imp:: Stdio ) ;
447
403
448
404
impl Stdio {
449
405
/// A new pipe should be arranged to connect the parent and child processes.
450
406
#[ stable( feature = "process" , since = "1.0.0" ) ]
451
- pub fn piped ( ) -> Stdio { Stdio ( StdioImp :: MakePipe ) }
407
+ pub fn piped ( ) -> Stdio { Stdio ( imp :: Stdio :: MakePipe ) }
452
408
453
409
/// The child inherits from the corresponding parent descriptor.
454
410
#[ stable( feature = "process" , since = "1.0.0" ) ]
455
- pub fn inherit ( ) -> Stdio { Stdio ( StdioImp :: Inherit ) }
411
+ pub fn inherit ( ) -> Stdio { Stdio ( imp :: Stdio :: Inherit ) }
456
412
457
413
/// This stream will be ignored. This is the equivalent of attaching the
458
414
/// stream to `/dev/null`
459
415
#[ stable( feature = "process" , since = "1.0.0" ) ]
460
- pub fn null ( ) -> Stdio { Stdio ( StdioImp :: None ) }
416
+ pub fn null ( ) -> Stdio { Stdio ( imp :: Stdio :: Null ) }
461
417
}
462
418
463
- impl FromInner < imp:: RawStdio > for Stdio {
464
- fn from_inner ( inner : imp:: RawStdio ) -> Stdio {
465
- Stdio ( StdioImp :: Raw ( inner) )
419
+ impl FromInner < imp:: Stdio > for Stdio {
420
+ fn from_inner ( inner : imp:: Stdio ) -> Stdio {
421
+ Stdio ( inner)
466
422
}
467
423
}
468
424
@@ -506,34 +462,7 @@ impl Child {
506
462
/// SIGKILL on unix platforms.
507
463
#[ stable( feature = "process" , since = "1.0.0" ) ]
508
464
pub fn kill ( & mut self ) -> io:: Result < ( ) > {
509
- #[ cfg( unix) ] fn collect_status ( p : & mut Child ) {
510
- // On Linux (and possibly other unices), a process that has exited will
511
- // continue to accept signals because it is "defunct". The delivery of
512
- // signals will only fail once the child has been reaped. For this
513
- // reason, if the process hasn't exited yet, then we attempt to collect
514
- // their status with WNOHANG.
515
- if p. status . is_none ( ) {
516
- match p. handle . try_wait ( ) {
517
- Some ( status) => { p. status = Some ( status) ; }
518
- None => { }
519
- }
520
- }
521
- }
522
- #[ cfg( windows) ] fn collect_status ( _p : & mut Child ) { }
523
-
524
- collect_status ( self ) ;
525
-
526
- // if the process has finished, and therefore had waitpid called,
527
- // and we kill it, then on unix we might ending up killing a
528
- // newer process that happens to have the same (re-used) id
529
- if self . status . is_some ( ) {
530
- return Err ( Error :: new (
531
- ErrorKind :: InvalidInput ,
532
- "invalid argument: can't kill an exited process" ,
533
- ) )
534
- }
535
-
536
- unsafe { self . handle . kill ( ) }
465
+ self . handle . kill ( )
537
466
}
538
467
539
468
/// Returns the OS-assigned process identifier associated with this child.
@@ -553,14 +482,7 @@ impl Child {
553
482
#[ stable( feature = "process" , since = "1.0.0" ) ]
554
483
pub fn wait ( & mut self ) -> io:: Result < ExitStatus > {
555
484
drop ( self . stdin . take ( ) ) ;
556
- match self . status {
557
- Some ( code) => Ok ( ExitStatus ( code) ) ,
558
- None => {
559
- let status = try!( self . handle . wait ( ) ) ;
560
- self . status = Some ( status) ;
561
- Ok ( ExitStatus ( status) )
562
- }
563
- }
485
+ self . handle . wait ( ) . map ( ExitStatus )
564
486
}
565
487
566
488
/// Simultaneously waits for the child to exit and collect all remaining
0 commit comments