broker_tokio/process/
mod.rs

1//! An implementation of asynchronous process management for Tokio.
2//!
3//! This module provides a [`Command`] struct that imitates the interface of the
4//! [`std::process::Command`] type in the standard library, but provides asynchronous versions of
5//! functions that create processes. These functions (`spawn`, `status`, `output` and their
6//! variants) return "future aware" types that interoperate with Tokio. The asynchronous process
7//! support is provided through signal handling on Unix and system APIs on Windows.
8//!
9//! # Examples
10//!
11//! Here's an example program which will spawn `echo hello world` and then wait
12//! for it complete.
13//!
14//! ```no_run
15//! use tokio::process::Command;
16//!
17//! #[tokio::main]
18//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
19//!     // The usage is the same as with the standard library's `Command` type, however the value
20//!     // returned from `spawn` is a `Result` containing a `Future`.
21//!     let child = Command::new("echo").arg("hello").arg("world")
22//!                         .spawn();
23//!
24//!     // Make sure our child succeeded in spawning and process the result
25//!     let future = child.expect("failed to spawn");
26//!
27//!     // Await until the future (and the command) completes
28//!     let status = future.await?;
29//!     println!("the command exited with: {}", status);
30//!     Ok(())
31//! }
32//! ```
33//!
34//! Next, let's take a look at an example where we not only spawn `echo hello
35//! world` but we also capture its output.
36//!
37//! ```no_run
38//! use tokio::process::Command;
39//!
40//! #[tokio::main]
41//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
42//!     // Like above, but use `output` which returns a future instead of
43//!     // immediately returning the `Child`.
44//!     let output = Command::new("echo").arg("hello").arg("world")
45//!                         .output();
46//!
47//!     let output = output.await?;
48//!
49//!     assert!(output.status.success());
50//!     assert_eq!(output.stdout, b"hello world\n");
51//!     Ok(())
52//! }
53//! ```
54//!
55//! We can also read input line by line.
56//!
57//! ```no_run
58//! use tokio::io::{BufReader, AsyncBufReadExt};
59//! use tokio::process::Command;
60//!
61//! use std::process::Stdio;
62//!
63//! #[tokio::main]
64//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
65//!     let mut cmd = Command::new("cat");
66//!
67//!     // Specify that we want the command's standard output piped back to us.
68//!     // By default, standard input/output/error will be inherited from the
69//!     // current process (for example, this means that standard input will
70//!     // come from the keyboard and standard output/error will go directly to
71//!     // the terminal if this process is invoked from the command line).
72//!     cmd.stdout(Stdio::piped());
73//!
74//!     let mut child = cmd.spawn()
75//!         .expect("failed to spawn command");
76//!
77//!     let stdout = child.stdout.take()
78//!         .expect("child did not have a handle to stdout");
79//!
80//!     let mut reader = BufReader::new(stdout).lines();
81//!
82//!     // Ensure the child process is spawned in the runtime so it can
83//!     // make progress on its own while we await for any output.
84//!     tokio::spawn(async {
85//!         let status = child.await
86//!             .expect("child process encountered an error");
87//!
88//!         println!("child status was: {}", status);
89//!     });
90//!
91//!     while let Some(line) = reader.next_line().await? {
92//!         println!("Line: {}", line);
93//!     }
94//!
95//!     Ok(())
96//! }
97//! ```
98//!
99//! # Caveats
100//!
101//! Similar to the behavior to the standard library, and unlike the futures
102//! paradigm of dropping-implies-cancellation, a spawned process will, by
103//! default, continue to execute even after the `Child` handle has been dropped.
104//!
105//! The `Command::kill_on_drop` method can be used to modify this behavior
106//! and kill the child process if the `Child` wrapper is dropped before it
107//! has exited.
108//!
109//! [`Command`]: crate::process::Command
110
111#[path = "unix/mod.rs"]
112#[cfg(unix)]
113mod imp;
114
115#[path = "windows.rs"]
116#[cfg(windows)]
117mod imp;
118
119mod kill;
120
121use crate::io::{AsyncRead, AsyncWrite};
122use crate::process::kill::Kill;
123
124use std::ffi::OsStr;
125use std::future::Future;
126use std::io;
127#[cfg(unix)]
128use std::os::unix::process::CommandExt;
129#[cfg(windows)]
130use std::os::windows::process::CommandExt;
131use std::path::Path;
132use std::pin::Pin;
133use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
134use std::task::Context;
135use std::task::Poll;
136
137/// This structure mimics the API of [`std::process::Command`] found in the standard library, but
138/// replaces functions that create a process with an asynchronous variant. The main provided
139/// asynchronous functions are [spawn](Command::spawn), [status](Command::status), and
140/// [output](Command::output).
141///
142/// `Command` uses asynchronous versions of some `std` types (for example [`Child`]).
143#[derive(Debug)]
144pub struct Command {
145    std: StdCommand,
146    kill_on_drop: bool,
147}
148
149pub(crate) struct SpawnedChild {
150    child: imp::Child,
151    stdin: Option<imp::ChildStdin>,
152    stdout: Option<imp::ChildStdout>,
153    stderr: Option<imp::ChildStderr>,
154}
155
156impl Command {
157    /// Constructs a new `Command` for launching the program at
158    /// path `program`, with the following default configuration:
159    ///
160    /// * No arguments to the program
161    /// * Inherit the current process's environment
162    /// * Inherit the current process's working directory
163    /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
164    ///
165    /// Builder methods are provided to change these defaults and
166    /// otherwise configure the process.
167    ///
168    /// If `program` is not an absolute path, the `PATH` will be searched in
169    /// an OS-defined way.
170    ///
171    /// The search path to be used may be controlled by setting the
172    /// `PATH` environment variable on the Command,
173    /// but this has some implementation limitations on Windows
174    /// (see issue rust-lang/rust#37519).
175    ///
176    /// # Examples
177    ///
178    /// Basic usage:
179    ///
180    /// ```no_run
181    /// use tokio::process::Command;
182    /// let command = Command::new("sh");
183    /// ```
184    pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
185        Self::from(StdCommand::new(program))
186    }
187
188    /// Adds an argument to pass to the program.
189    ///
190    /// Only one argument can be passed per use. So instead of:
191    ///
192    /// ```no_run
193    /// tokio::process::Command::new("sh")
194    ///   .arg("-C /path/to/repo");
195    /// ```
196    ///
197    /// usage would be:
198    ///
199    /// ```no_run
200    /// tokio::process::Command::new("sh")
201    ///   .arg("-C")
202    ///   .arg("/path/to/repo");
203    /// ```
204    ///
205    /// To pass multiple arguments see [`args`].
206    ///
207    /// [`args`]: #method.args
208    ///
209    /// # Examples
210    ///
211    /// Basic usage:
212    ///
213    /// ```no_run
214    /// use tokio::process::Command;
215    ///
216    /// let command = Command::new("ls")
217    ///         .arg("-l")
218    ///         .arg("-a");
219    /// ```
220    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
221        self.std.arg(arg);
222        self
223    }
224
225    /// Adds multiple arguments to pass to the program.
226    ///
227    /// To pass a single argument see [`arg`].
228    ///
229    /// [`arg`]: #method.arg
230    ///
231    /// # Examples
232    ///
233    /// Basic usage:
234    ///
235    /// ```no_run
236    /// use tokio::process::Command;
237    ///
238    /// let command = Command::new("ls")
239    ///         .args(&["-l", "-a"]);
240    /// ```
241    pub fn args<I, S>(&mut self, args: I) -> &mut Command
242    where
243        I: IntoIterator<Item = S>,
244        S: AsRef<OsStr>,
245    {
246        self.std.args(args);
247        self
248    }
249
250    /// Inserts or updates an environment variable mapping.
251    ///
252    /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
253    /// and case-sensitive on all other platforms.
254    ///
255    /// # Examples
256    ///
257    /// Basic usage:
258    ///
259    /// ```no_run
260    /// use tokio::process::Command;
261    ///
262    /// let command = Command::new("ls")
263    ///         .env("PATH", "/bin");
264    /// ```
265    pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
266    where
267        K: AsRef<OsStr>,
268        V: AsRef<OsStr>,
269    {
270        self.std.env(key, val);
271        self
272    }
273
274    /// Adds or updates multiple environment variable mappings.
275    ///
276    /// # Examples
277    ///
278    /// Basic usage:
279    ///
280    /// ```no_run
281    /// use tokio::process::Command;
282    /// use std::process::{Stdio};
283    /// use std::env;
284    /// use std::collections::HashMap;
285    ///
286    /// let filtered_env : HashMap<String, String> =
287    ///     env::vars().filter(|&(ref k, _)|
288    ///         k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
289    ///     ).collect();
290    ///
291    /// let command = Command::new("printenv")
292    ///         .stdin(Stdio::null())
293    ///         .stdout(Stdio::inherit())
294    ///         .env_clear()
295    ///         .envs(&filtered_env);
296    /// ```
297    pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
298    where
299        I: IntoIterator<Item = (K, V)>,
300        K: AsRef<OsStr>,
301        V: AsRef<OsStr>,
302    {
303        self.std.envs(vars);
304        self
305    }
306
307    /// Removes an environment variable mapping.
308    ///
309    /// # Examples
310    ///
311    /// Basic usage:
312    ///
313    /// ```no_run
314    /// use tokio::process::Command;
315    ///
316    /// let command = Command::new("ls")
317    ///         .env_remove("PATH");
318    /// ```
319    pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
320        self.std.env_remove(key);
321        self
322    }
323
324    /// Clears the entire environment map for the child process.
325    ///
326    /// # Examples
327    ///
328    /// Basic usage:
329    ///
330    /// ```no_run
331    /// use tokio::process::Command;
332    ///
333    /// let command = Command::new("ls")
334    ///         .env_clear();
335    /// ```
336    pub fn env_clear(&mut self) -> &mut Command {
337        self.std.env_clear();
338        self
339    }
340
341    /// Sets the working directory for the child process.
342    ///
343    /// # Platform-specific behavior
344    ///
345    /// If the program path is relative (e.g., `"./script.sh"`), it's ambiguous
346    /// whether it should be interpreted relative to the parent's working
347    /// directory or relative to `current_dir`. The behavior in this case is
348    /// platform specific and unstable, and it's recommended to use
349    /// [`canonicalize`] to get an absolute program path instead.
350    ///
351    /// [`canonicalize`]: crate::fs::canonicalize()
352    ///
353    /// # Examples
354    ///
355    /// Basic usage:
356    ///
357    /// ```no_run
358    /// use tokio::process::Command;
359    ///
360    /// let command = Command::new("ls")
361    ///         .current_dir("/bin");
362    /// ```
363    pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
364        self.std.current_dir(dir);
365        self
366    }
367
368    /// Configuration for the child process's standard input (stdin) handle.
369    ///
370    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
371    /// defaults to [`piped`] when used with `output`.
372    ///
373    /// [`inherit`]: std::process::Stdio::inherit
374    /// [`piped`]: std::process::Stdio::piped
375    ///
376    /// # Examples
377    ///
378    /// Basic usage:
379    ///
380    /// ```no_run
381    /// use std::process::{Stdio};
382    /// use tokio::process::Command;
383    ///
384    /// let command = Command::new("ls")
385    ///         .stdin(Stdio::null());
386    /// ```
387    pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
388        self.std.stdin(cfg);
389        self
390    }
391
392    /// Configuration for the child process's standard output (stdout) handle.
393    ///
394    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
395    /// defaults to [`piped`] when used with `output`.
396    ///
397    /// [`inherit`]: std::process::Stdio::inherit
398    /// [`piped`]: std::process::Stdio::piped
399    ///
400    /// # Examples
401    ///
402    /// Basic usage:
403    ///
404    /// ```no_run
405    /// use tokio::process::Command;;
406    /// use std::process::Stdio;
407    ///
408    /// let command = Command::new("ls")
409    ///         .stdout(Stdio::null());
410    /// ```
411    pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
412        self.std.stdout(cfg);
413        self
414    }
415
416    /// Configuration for the child process's standard error (stderr) handle.
417    ///
418    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
419    /// defaults to [`piped`] when used with `output`.
420    ///
421    /// [`inherit`]: std::process::Stdio::inherit
422    /// [`piped`]: std::process::Stdio::piped
423    ///
424    /// # Examples
425    ///
426    /// Basic usage:
427    ///
428    /// ```no_run
429    /// use tokio::process::Command;;
430    /// use std::process::{Stdio};
431    ///
432    /// let command = Command::new("ls")
433    ///         .stderr(Stdio::null());
434    /// ```
435    pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
436        self.std.stderr(cfg);
437        self
438    }
439
440    /// Controls whether a `kill` operation should be invoked on a spawned child
441    /// process when its corresponding `Child` handle is dropped.
442    ///
443    /// By default, this value is assumed to be `false`, meaning the next spawned
444    /// process will not be killed on drop, similar to the behavior of the standard
445    /// library.
446    pub fn kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Command {
447        self.kill_on_drop = kill_on_drop;
448        self
449    }
450
451    /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
452    ///
453    /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`.
454    ///
455    /// [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
456    #[cfg(windows)]
457    pub fn creation_flags(&mut self, flags: u32) -> &mut Command {
458        self.std.creation_flags(flags);
459        self
460    }
461
462    /// Sets the child process's user ID. This translates to a
463    /// `setuid` call in the child process. Failure in the `setuid`
464    /// call will cause the spawn to fail.
465    #[cfg(unix)]
466    pub fn uid(&mut self, id: u32) -> &mut Command {
467        self.std.uid(id);
468        self
469    }
470
471    /// Similar to `uid`, but sets the group ID of the child process. This has
472    /// the same semantics as the `uid` field.
473    #[cfg(unix)]
474    pub fn gid(&mut self, id: u32) -> &mut Command {
475        self.std.gid(id);
476        self
477    }
478
479    /// Schedules a closure to be run just before the `exec` function is
480    /// invoked.
481    ///
482    /// The closure is allowed to return an I/O error whose OS error code will
483    /// be communicated back to the parent and returned as an error from when
484    /// the spawn was requested.
485    ///
486    /// Multiple closures can be registered and they will be called in order of
487    /// their registration. If a closure returns `Err` then no further closures
488    /// will be called and the spawn operation will immediately return with a
489    /// failure.
490    ///
491    /// # Safety
492    ///
493    /// This closure will be run in the context of the child process after a
494    /// `fork`. This primarily means that any modifications made to memory on
495    /// behalf of this closure will **not** be visible to the parent process.
496    /// This is often a very constrained environment where normal operations
497    /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
498    /// other threads perhaps still running when the `fork` was run).
499    ///
500    /// This also means that all resources such as file descriptors and
501    /// memory-mapped regions got duplicated. It is your responsibility to make
502    /// sure that the closure does not violate library invariants by making
503    /// invalid use of these duplicates.
504    ///
505    /// When this closure is run, aspects such as the stdio file descriptors and
506    /// working directory have successfully been changed, so output to these
507    /// locations may not appear where intended.
508    #[cfg(unix)]
509    pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Command
510    where
511        F: FnMut() -> io::Result<()> + Send + Sync + 'static,
512    {
513        self.std.pre_exec(f);
514        self
515    }
516
517    /// Executes the command as a child process, returning a handle to it.
518    ///
519    /// By default, stdin, stdout and stderr are inherited from the parent.
520    ///
521    /// This method will spawn the child process synchronously and return a
522    /// handle to a future-aware child process. The `Child` returned implements
523    /// `Future` itself to acquire the `ExitStatus` of the child, and otherwise
524    /// the `Child` has methods to acquire handles to the stdin, stdout, and
525    /// stderr streams.
526    ///
527    /// All I/O this child does will be associated with the current default
528    /// event loop.
529    ///
530    /// # Caveats
531    ///
532    /// Similar to the behavior to the standard library, and unlike the futures
533    /// paradigm of dropping-implies-cancellation, the spawned process will, by
534    /// default, continue to execute even after the `Child` handle has been dropped.
535    ///
536    /// The `Command::kill_on_drop` method can be used to modify this behavior
537    /// and kill the child process if the `Child` wrapper is dropped before it
538    /// has exited.
539    ///
540    /// # Examples
541    ///
542    /// Basic usage:
543    ///
544    /// ```no_run
545    /// use tokio::process::Command;
546    ///
547    /// async fn run_ls() -> std::process::ExitStatus {
548    ///     Command::new("ls")
549    ///         .spawn()
550    ///         .expect("ls command failed to start")
551    ///         .await
552    ///         .expect("ls command failed to run")
553    /// }
554    /// ```
555    pub fn spawn(&mut self) -> io::Result<Child> {
556        imp::spawn_child(&mut self.std).map(|spawned_child| Child {
557            child: ChildDropGuard {
558                inner: spawned_child.child,
559                kill_on_drop: self.kill_on_drop,
560            },
561            stdin: spawned_child.stdin.map(|inner| ChildStdin { inner }),
562            stdout: spawned_child.stdout.map(|inner| ChildStdout { inner }),
563            stderr: spawned_child.stderr.map(|inner| ChildStderr { inner }),
564        })
565    }
566
567    /// Executes a command as a child process, waiting for it to finish and
568    /// collecting its exit status.
569    ///
570    /// By default, stdin, stdout and stderr are inherited from the parent.
571    /// If any input/output handles are set to a pipe then they will be immediately
572    /// closed after the child is spawned.
573    ///
574    /// All I/O this child does will be associated with the current default
575    /// event loop.
576    ///
577    /// If this future is dropped before the future resolves, then
578    /// the child will be killed, if it was spawned.
579    ///
580    /// # Errors
581    ///
582    /// This future will return an error if the child process cannot be spawned
583    /// or if there is an error while awaiting its status.
584    ///
585    /// # Examples
586    ///
587    /// Basic usage:
588    ///
589    /// ```no_run
590    /// use tokio::process::Command;
591    ///
592    /// async fn run_ls() -> std::process::ExitStatus {
593    ///     Command::new("ls")
594    ///         .status()
595    ///         .await
596    ///         .expect("ls command failed to run")
597    /// }
598    pub fn status(&mut self) -> impl Future<Output = io::Result<ExitStatus>> {
599        let child = self.spawn();
600
601        async {
602            let mut child = child?;
603
604            // Ensure we close any stdio handles so we can't deadlock
605            // waiting on the child which may be waiting to read/write
606            // to a pipe we're holding.
607            child.stdin.take();
608            child.stdout.take();
609            child.stderr.take();
610
611            child.await
612        }
613    }
614
615    /// Executes the command as a child process, waiting for it to finish and
616    /// collecting all of its output.
617    ///
618    /// > **Note**: this method, unlike the standard library, will
619    /// > unconditionally configure the stdout/stderr handles to be pipes, even
620    /// > if they have been previously configured. If this is not desired then
621    /// > the `spawn` method should be used in combination with the
622    /// > `wait_with_output` method on child.
623    ///
624    /// This method will return a future representing the collection of the
625    /// child process's stdout/stderr. It will resolve to
626    /// the `Output` type in the standard library, containing `stdout` and
627    /// `stderr` as `Vec<u8>` along with an `ExitStatus` representing how the
628    /// process exited.
629    ///
630    /// All I/O this child does will be associated with the current default
631    /// event loop.
632    ///
633    /// If this future is dropped before the future resolves, then
634    /// the child will be killed, if it was spawned.
635    ///
636    /// # Examples
637    ///
638    /// Basic usage:
639    ///
640    /// ```no_run
641    /// use tokio::process::Command;
642    ///
643    /// async fn run_ls() {
644    ///     let output: std::process::Output = Command::new("ls")
645    ///         .output()
646    ///         .await
647    ///         .expect("ls command failed to run");
648    ///     println!("stderr of ls: {:?}", output.stderr);
649    /// }
650    pub fn output(&mut self) -> impl Future<Output = io::Result<Output>> {
651        self.std.stdout(Stdio::piped());
652        self.std.stderr(Stdio::piped());
653
654        let child = self.spawn();
655
656        async { child?.wait_with_output().await }
657    }
658}
659
660impl From<StdCommand> for Command {
661    fn from(std: StdCommand) -> Command {
662        Command {
663            std,
664            kill_on_drop: false,
665        }
666    }
667}
668
669/// A drop guard which can ensure the child process is killed on drop if specified.
670#[derive(Debug)]
671struct ChildDropGuard<T: Kill> {
672    inner: T,
673    kill_on_drop: bool,
674}
675
676impl<T: Kill> Kill for ChildDropGuard<T> {
677    fn kill(&mut self) -> io::Result<()> {
678        let ret = self.inner.kill();
679
680        if ret.is_ok() {
681            self.kill_on_drop = false;
682        }
683
684        ret
685    }
686}
687
688impl<T: Kill> Drop for ChildDropGuard<T> {
689    fn drop(&mut self) {
690        if self.kill_on_drop {
691            drop(self.kill());
692        }
693    }
694}
695
696impl<T, E, F> Future for ChildDropGuard<F>
697where
698    F: Future<Output = Result<T, E>> + Kill + Unpin,
699{
700    type Output = Result<T, E>;
701
702    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
703        let ret = Pin::new(&mut self.inner).poll(cx);
704
705        if let Poll::Ready(Ok(_)) = ret {
706            // Avoid the overhead of trying to kill a reaped process
707            self.kill_on_drop = false;
708        }
709
710        ret
711    }
712}
713
714/// Representation of a child process spawned onto an event loop.
715///
716/// This type is also a future which will yield the `ExitStatus` of the
717/// underlying child process. A `Child` here also provides access to information
718/// like the OS-assigned identifier and the stdio streams.
719///
720/// # Caveats
721/// Similar to the behavior to the standard library, and unlike the futures
722/// paradigm of dropping-implies-cancellation, a spawned process will, by
723/// default, continue to execute even after the `Child` handle has been dropped.
724///
725/// The `Command::kill_on_drop` method can be used to modify this behavior
726/// and kill the child process if the `Child` wrapper is dropped before it
727/// has exited.
728#[must_use = "futures do nothing unless polled"]
729#[derive(Debug)]
730pub struct Child {
731    child: ChildDropGuard<imp::Child>,
732
733    /// The handle for writing to the child's standard input (stdin), if it has
734    /// been captured.
735    pub stdin: Option<ChildStdin>,
736
737    /// The handle for reading from the child's standard output (stdout), if it
738    /// has been captured.
739    pub stdout: Option<ChildStdout>,
740
741    /// The handle for reading from the child's standard error (stderr), if it
742    /// has been captured.
743    pub stderr: Option<ChildStderr>,
744}
745
746impl Child {
747    /// Returns the OS-assigned process identifier associated with this child.
748    pub fn id(&self) -> u32 {
749        self.child.inner.id()
750    }
751
752    /// Forces the child to exit.
753    ///
754    /// This is equivalent to sending a SIGKILL on unix platforms.
755    pub fn kill(&mut self) -> io::Result<()> {
756        self.child.kill()
757    }
758
759    #[doc(hidden)]
760    #[deprecated(note = "please use `child.stdin` instead")]
761    pub fn stdin(&mut self) -> &mut Option<ChildStdin> {
762        &mut self.stdin
763    }
764
765    #[doc(hidden)]
766    #[deprecated(note = "please use `child.stdout` instead")]
767    pub fn stdout(&mut self) -> &mut Option<ChildStdout> {
768        &mut self.stdout
769    }
770
771    #[doc(hidden)]
772    #[deprecated(note = "please use `child.stderr` instead")]
773    pub fn stderr(&mut self) -> &mut Option<ChildStderr> {
774        &mut self.stderr
775    }
776
777    /// Returns a future that will resolve to an `Output`, containing the exit
778    /// status, stdout, and stderr of the child process.
779    ///
780    /// The returned future will simultaneously waits for the child to exit and
781    /// collect all remaining output on the stdout/stderr handles, returning an
782    /// `Output` instance.
783    ///
784    /// The stdin handle to the child process, if any, will be closed before
785    /// waiting. This helps avoid deadlock: it ensures that the child does not
786    /// block waiting for input from the parent, while the parent waits for the
787    /// child to exit.
788    ///
789    /// By default, stdin, stdout and stderr are inherited from the parent. In
790    /// order to capture the output into this `Output` it is necessary to create
791    /// new pipes between parent and child. Use `stdout(Stdio::piped())` or
792    /// `stderr(Stdio::piped())`, respectively, when creating a `Command`.
793    pub async fn wait_with_output(mut self) -> io::Result<Output> {
794        use crate::future::try_join3;
795
796        async fn read_to_end<A: AsyncRead + Unpin>(io: Option<A>) -> io::Result<Vec<u8>> {
797            let mut vec = Vec::new();
798            if let Some(mut io) = io {
799                crate::io::util::read_to_end(&mut io, &mut vec).await?;
800            }
801            Ok(vec)
802        }
803
804        drop(self.stdin.take());
805        let stdout_fut = read_to_end(self.stdout.take());
806        let stderr_fut = read_to_end(self.stderr.take());
807
808        let (status, stdout, stderr) = try_join3(self, stdout_fut, stderr_fut).await?;
809
810        Ok(Output {
811            status,
812            stdout,
813            stderr,
814        })
815    }
816}
817
818impl Future for Child {
819    type Output = io::Result<ExitStatus>;
820
821    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
822        Pin::new(&mut self.child).poll(cx)
823    }
824}
825
826/// The standard input stream for spawned children.
827///
828/// This type implements the `AsyncWrite` trait to pass data to the stdin handle of
829/// handle of a child process asynchronously.
830#[derive(Debug)]
831pub struct ChildStdin {
832    inner: imp::ChildStdin,
833}
834
835/// The standard output stream for spawned children.
836///
837/// This type implements the `AsyncRead` trait to read data from the stdout
838/// handle of a child process asynchronously.
839#[derive(Debug)]
840pub struct ChildStdout {
841    inner: imp::ChildStdout,
842}
843
844/// The standard error stream for spawned children.
845///
846/// This type implements the `AsyncRead` trait to read data from the stderr
847/// handle of a child process asynchronously.
848#[derive(Debug)]
849pub struct ChildStderr {
850    inner: imp::ChildStderr,
851}
852
853impl AsyncWrite for ChildStdin {
854    fn poll_write(
855        mut self: Pin<&mut Self>,
856        cx: &mut Context<'_>,
857        buf: &[u8],
858    ) -> Poll<io::Result<usize>> {
859        Pin::new(&mut self.inner).poll_write(cx, buf)
860    }
861
862    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
863        Pin::new(&mut self.inner).poll_flush(cx)
864    }
865
866    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
867        Pin::new(&mut self.inner).poll_shutdown(cx)
868    }
869}
870
871impl AsyncRead for ChildStdout {
872    fn poll_read(
873        mut self: Pin<&mut Self>,
874        cx: &mut Context<'_>,
875        buf: &mut [u8],
876    ) -> Poll<io::Result<usize>> {
877        Pin::new(&mut self.inner).poll_read(cx, buf)
878    }
879}
880
881impl AsyncRead for ChildStderr {
882    fn poll_read(
883        mut self: Pin<&mut Self>,
884        cx: &mut Context<'_>,
885        buf: &mut [u8],
886    ) -> Poll<io::Result<usize>> {
887        Pin::new(&mut self.inner).poll_read(cx, buf)
888    }
889}
890
891#[cfg(unix)]
892mod sys {
893    use std::os::unix::io::{AsRawFd, RawFd};
894
895    use super::{ChildStderr, ChildStdin, ChildStdout};
896
897    impl AsRawFd for ChildStdin {
898        fn as_raw_fd(&self) -> RawFd {
899            self.inner.get_ref().as_raw_fd()
900        }
901    }
902
903    impl AsRawFd for ChildStdout {
904        fn as_raw_fd(&self) -> RawFd {
905            self.inner.get_ref().as_raw_fd()
906        }
907    }
908
909    impl AsRawFd for ChildStderr {
910        fn as_raw_fd(&self) -> RawFd {
911            self.inner.get_ref().as_raw_fd()
912        }
913    }
914}
915
916#[cfg(windows)]
917mod sys {
918    use std::os::windows::io::{AsRawHandle, RawHandle};
919
920    use super::{ChildStderr, ChildStdin, ChildStdout};
921
922    impl AsRawHandle for ChildStdin {
923        fn as_raw_handle(&self) -> RawHandle {
924            self.inner.get_ref().as_raw_handle()
925        }
926    }
927
928    impl AsRawHandle for ChildStdout {
929        fn as_raw_handle(&self) -> RawHandle {
930            self.inner.get_ref().as_raw_handle()
931        }
932    }
933
934    impl AsRawHandle for ChildStderr {
935        fn as_raw_handle(&self) -> RawHandle {
936            self.inner.get_ref().as_raw_handle()
937        }
938    }
939}
940
941#[cfg(all(test, not(loom)))]
942mod test {
943    use super::kill::Kill;
944    use super::ChildDropGuard;
945
946    use futures::future::FutureExt;
947    use std::future::Future;
948    use std::io;
949    use std::pin::Pin;
950    use std::task::{Context, Poll};
951
952    struct Mock {
953        num_kills: usize,
954        num_polls: usize,
955        poll_result: Poll<Result<(), ()>>,
956    }
957
958    impl Mock {
959        fn new() -> Self {
960            Self::with_result(Poll::Pending)
961        }
962
963        fn with_result(result: Poll<Result<(), ()>>) -> Self {
964            Self {
965                num_kills: 0,
966                num_polls: 0,
967                poll_result: result,
968            }
969        }
970    }
971
972    impl Kill for Mock {
973        fn kill(&mut self) -> io::Result<()> {
974            self.num_kills += 1;
975            Ok(())
976        }
977    }
978
979    impl Future for Mock {
980        type Output = Result<(), ()>;
981
982        fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
983            let inner = Pin::get_mut(self);
984            inner.num_polls += 1;
985            inner.poll_result
986        }
987    }
988
989    #[test]
990    fn kills_on_drop_if_specified() {
991        let mut mock = Mock::new();
992
993        {
994            let guard = ChildDropGuard {
995                inner: &mut mock,
996                kill_on_drop: true,
997            };
998            drop(guard);
999        }
1000
1001        assert_eq!(1, mock.num_kills);
1002        assert_eq!(0, mock.num_polls);
1003    }
1004
1005    #[test]
1006    fn no_kill_on_drop_by_default() {
1007        let mut mock = Mock::new();
1008
1009        {
1010            let guard = ChildDropGuard {
1011                inner: &mut mock,
1012                kill_on_drop: false,
1013            };
1014            drop(guard);
1015        }
1016
1017        assert_eq!(0, mock.num_kills);
1018        assert_eq!(0, mock.num_polls);
1019    }
1020
1021    #[test]
1022    fn no_kill_if_already_killed() {
1023        let mut mock = Mock::new();
1024
1025        {
1026            let mut guard = ChildDropGuard {
1027                inner: &mut mock,
1028                kill_on_drop: true,
1029            };
1030            let _ = guard.kill();
1031            drop(guard);
1032        }
1033
1034        assert_eq!(1, mock.num_kills);
1035        assert_eq!(0, mock.num_polls);
1036    }
1037
1038    #[test]
1039    fn no_kill_if_reaped() {
1040        let mut mock_pending = Mock::with_result(Poll::Pending);
1041        let mut mock_reaped = Mock::with_result(Poll::Ready(Ok(())));
1042        let mut mock_err = Mock::with_result(Poll::Ready(Err(())));
1043
1044        let waker = futures::task::noop_waker();
1045        let mut context = Context::from_waker(&waker);
1046        {
1047            let mut guard = ChildDropGuard {
1048                inner: &mut mock_pending,
1049                kill_on_drop: true,
1050            };
1051            let _ = guard.poll_unpin(&mut context);
1052
1053            let mut guard = ChildDropGuard {
1054                inner: &mut mock_reaped,
1055                kill_on_drop: true,
1056            };
1057            let _ = guard.poll_unpin(&mut context);
1058
1059            let mut guard = ChildDropGuard {
1060                inner: &mut mock_err,
1061                kill_on_drop: true,
1062            };
1063            let _ = guard.poll_unpin(&mut context);
1064        }
1065
1066        assert_eq!(1, mock_pending.num_kills);
1067        assert_eq!(1, mock_pending.num_polls);
1068
1069        assert_eq!(0, mock_reaped.num_kills);
1070        assert_eq!(1, mock_reaped.num_polls);
1071
1072        assert_eq!(1, mock_err.num_kills);
1073        assert_eq!(1, mock_err.num_polls);
1074    }
1075}