1111//! Working with processes.
1212
1313#![ stable( feature = "process" , since = "1.0.0" ) ]
14- #![ allow( non_upper_case_globals) ]
1514
1615use prelude:: v1:: * ;
1716use io:: prelude:: * ;
1817
1918use ffi:: OsStr ;
2019use fmt;
21- use io:: { self , Error , ErrorKind } ;
22- use path;
20+ use io;
21+ use path:: Path ;
2322use str;
24- use sys:: pipe:: { self , AnonPipe } ;
23+ use sys:: pipe:: AnonPipe ;
2524use sys:: process as imp;
2625use sys_common:: { AsInner , AsInnerMut , FromInner , IntoInner } ;
2726use thread:: { self , JoinHandle } ;
@@ -61,9 +60,6 @@ use thread::{self, JoinHandle};
6160pub struct Child {
6261 handle : imp:: Process ,
6362
64- /// None until wait() or wait_with_output() is called.
65- status : Option < imp:: ExitStatus > ,
66-
6763 /// The handle for writing to the child's stdin, if it has been captured
6864 #[ stable( feature = "process" , since = "1.0.0" ) ]
6965 pub stdin : Option < ChildStdin > ,
@@ -81,6 +77,17 @@ impl AsInner<imp::Process> for Child {
8177 fn as_inner ( & self ) -> & imp:: Process { & self . handle }
8278}
8379
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+
8491impl IntoInner < imp:: Process > for Child {
8592 fn into_inner ( self ) -> imp:: Process { self . handle }
8693}
@@ -110,6 +117,12 @@ impl IntoInner<AnonPipe> for ChildStdin {
110117 fn into_inner ( self ) -> AnonPipe { self . inner }
111118}
112119
120+ impl FromInner < AnonPipe > for ChildStdin {
121+ fn from_inner ( pipe : AnonPipe ) -> ChildStdin {
122+ ChildStdin { inner : pipe }
123+ }
124+ }
125+
113126/// A handle to a child process's stdout
114127#[ stable( feature = "process" , since = "1.0.0" ) ]
115128pub struct ChildStdout {
@@ -131,6 +144,12 @@ impl IntoInner<AnonPipe> for ChildStdout {
131144 fn into_inner ( self ) -> AnonPipe { self . inner }
132145}
133146
147+ impl FromInner < AnonPipe > for ChildStdout {
148+ fn from_inner ( pipe : AnonPipe ) -> ChildStdout {
149+ ChildStdout { inner : pipe }
150+ }
151+ }
152+
134153/// A handle to a child process's stderr
135154#[ stable( feature = "process" , since = "1.0.0" ) ]
136155pub struct ChildStderr {
@@ -152,6 +171,12 @@ impl IntoInner<AnonPipe> for ChildStderr {
152171 fn into_inner ( self ) -> AnonPipe { self . inner }
153172}
154173
174+ impl FromInner < AnonPipe > for ChildStderr {
175+ fn from_inner ( pipe : AnonPipe ) -> ChildStderr {
176+ ChildStderr { inner : pipe }
177+ }
178+ }
179+
155180/// The `Command` type acts as a process builder, providing fine-grained control
156181/// over how a new process should be spawned. A default configuration can be
157182/// generated using `Command::new(program)`, where `program` gives a path to the
@@ -171,11 +196,6 @@ impl IntoInner<AnonPipe> for ChildStderr {
171196#[ stable( feature = "process" , since = "1.0.0" ) ]
172197pub struct Command {
173198 inner : imp:: Command ,
174-
175- // Details explained in the builder methods
176- stdin : Option < Stdio > ,
177- stdout : Option < Stdio > ,
178- stderr : Option < Stdio > ,
179199}
180200
181201impl Command {
@@ -191,12 +211,7 @@ impl Command {
191211 /// otherwise configure the process.
192212 #[ stable( feature = "process" , since = "1.0.0" ) ]
193213 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 ( ) ) }
200215 }
201216
202217 /// Add an argument to pass to the program.
@@ -209,7 +224,9 @@ impl Command {
209224 /// Add multiple arguments to pass to the program.
210225 #[ stable( feature = "process" , since = "1.0.0" ) ]
211226 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+ }
213230 self
214231 }
215232
@@ -241,65 +258,38 @@ impl Command {
241258
242259 /// Sets the working directory for the child process.
243260 #[ 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 {
245262 self . inner . cwd ( dir. as_ref ( ) . as_ref ( ) ) ;
246263 self
247264 }
248265
249266 /// Configuration for the child process's stdin handle (file descriptor 0).
250267 #[ stable( feature = "process" , since = "1.0.0" ) ]
251268 pub fn stdin ( & mut self , cfg : Stdio ) -> & mut Command {
252- self . stdin = Some ( cfg) ;
269+ self . inner . stdin ( cfg. 0 ) ;
253270 self
254271 }
255272
256273 /// Configuration for the child process's stdout handle (file descriptor 1).
257274 #[ stable( feature = "process" , since = "1.0.0" ) ]
258275 pub fn stdout ( & mut self , cfg : Stdio ) -> & mut Command {
259- self . stdout = Some ( cfg) ;
276+ self . inner . stdout ( cfg. 0 ) ;
260277 self
261278 }
262279
263280 /// Configuration for the child process's stderr handle (file descriptor 2).
264281 #[ stable( feature = "process" , since = "1.0.0" ) ]
265282 pub fn stderr ( & mut self , cfg : Stdio ) -> & mut Command {
266- self . stderr = Some ( cfg) ;
283+ self . inner . stderr ( cfg. 0 ) ;
267284 self
268285 }
269286
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-
297287 /// Executes the command as a child process, returning a handle to it.
298288 ///
299289 /// By default, stdin, stdout and stderr are inherited from the parent.
300290 #[ stable( feature = "process" , since = "1.0.0" ) ]
301291 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 )
303293 }
304294
305295 /// Executes the command as a child process, waiting for it to finish and
@@ -322,7 +312,8 @@ impl Command {
322312 /// ```
323313 #[ stable( feature = "process" , since = "1.0.0" ) ]
324314 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 ( ) )
326317 }
327318
328319 /// Executes a command as a child process, waiting for it to finish and
@@ -365,33 +356,6 @@ impl AsInnerMut<imp::Command> for Command {
365356 fn as_inner_mut ( & mut self ) -> & mut imp:: Command { & mut self . inner }
366357}
367358
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-
395359/// The output of a finished process.
396360#[ derive( PartialEq , Eq , Clone ) ]
397361#[ stable( feature = "process" , since = "1.0.0" ) ]
@@ -435,34 +399,26 @@ impl fmt::Debug for Output {
435399
436400/// Describes what to do with a standard I/O stream for a child process.
437401#[ 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 ) ;
447403
448404impl Stdio {
449405 /// A new pipe should be arranged to connect the parent and child processes.
450406 #[ stable( feature = "process" , since = "1.0.0" ) ]
451- pub fn piped ( ) -> Stdio { Stdio ( StdioImp :: MakePipe ) }
407+ pub fn piped ( ) -> Stdio { Stdio ( imp :: Stdio :: MakePipe ) }
452408
453409 /// The child inherits from the corresponding parent descriptor.
454410 #[ stable( feature = "process" , since = "1.0.0" ) ]
455- pub fn inherit ( ) -> Stdio { Stdio ( StdioImp :: Inherit ) }
411+ pub fn inherit ( ) -> Stdio { Stdio ( imp :: Stdio :: Inherit ) }
456412
457413 /// This stream will be ignored. This is the equivalent of attaching the
458414 /// stream to `/dev/null`
459415 #[ stable( feature = "process" , since = "1.0.0" ) ]
460- pub fn null ( ) -> Stdio { Stdio ( StdioImp :: None ) }
416+ pub fn null ( ) -> Stdio { Stdio ( imp :: Stdio :: Null ) }
461417}
462418
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)
466422 }
467423}
468424
@@ -506,34 +462,7 @@ impl Child {
506462 /// SIGKILL on unix platforms.
507463 #[ stable( feature = "process" , since = "1.0.0" ) ]
508464 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 ( )
537466 }
538467
539468 /// Returns the OS-assigned process identifier associated with this child.
@@ -553,14 +482,7 @@ impl Child {
553482 #[ stable( feature = "process" , since = "1.0.0" ) ]
554483 pub fn wait ( & mut self ) -> io:: Result < ExitStatus > {
555484 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 )
564486 }
565487
566488 /// Simultaneously waits for the child to exit and collect all remaining
0 commit comments