madsim_real_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//! [`std::process::Command`]: std::process::Command
10//!
11//! # Examples
12//!
13//! Here's an example program which will spawn `echo hello world` and then wait
14//! for it complete.
15//!
16//! ```no_run
17//! use tokio::process::Command;
18//!
19//! #[tokio::main]
20//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
21//!     // The usage is similar as with the standard library's `Command` type
22//!     let mut child = Command::new("echo")
23//!         .arg("hello")
24//!         .arg("world")
25//!         .spawn()
26//!         .expect("failed to spawn");
27//!
28//!     // Await until the command completes
29//!     let status = child.wait().await?;
30//!     println!("the command exited with: {}", status);
31//!     Ok(())
32//! }
33//! ```
34//!
35//! Next, let's take a look at an example where we not only spawn `echo hello
36//! world` but we also capture its output.
37//!
38//! ```no_run
39//! use tokio::process::Command;
40//!
41//! #[tokio::main]
42//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
43//!     // Like above, but use `output` which returns a future instead of
44//!     // immediately returning the `Child`.
45//!     let output = Command::new("echo").arg("hello").arg("world")
46//!                         .output();
47//!
48//!     let output = output.await?;
49//!
50//!     assert!(output.status.success());
51//!     assert_eq!(output.stdout, b"hello world\n");
52//!     Ok(())
53//! }
54//! ```
55//!
56//! We can also read input line by line.
57//!
58//! ```no_run
59//! use tokio::io::{BufReader, AsyncBufReadExt};
60//! use tokio::process::Command;
61//!
62//! use std::process::Stdio;
63//!
64//! #[tokio::main]
65//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
66//!     let mut cmd = Command::new("cat");
67//!
68//!     // Specify that we want the command's standard output piped back to us.
69//!     // By default, standard input/output/error will be inherited from the
70//!     // current process (for example, this means that standard input will
71//!     // come from the keyboard and standard output/error will go directly to
72//!     // the terminal if this process is invoked from the command line).
73//!     cmd.stdout(Stdio::piped());
74//!
75//!     let mut child = cmd.spawn()
76//!         .expect("failed to spawn command");
77//!
78//!     let stdout = child.stdout.take()
79//!         .expect("child did not have a handle to stdout");
80//!
81//!     let mut reader = BufReader::new(stdout).lines();
82//!
83//!     // Ensure the child process is spawned in the runtime so it can
84//!     // make progress on its own while we await for any output.
85//!     tokio::spawn(async move {
86//!         let status = child.wait().await
87//!             .expect("child process encountered an error");
88//!
89//!         println!("child status was: {}", status);
90//!     });
91//!
92//!     while let Some(line) = reader.next_line().await? {
93//!         println!("Line: {}", line);
94//!     }
95//!
96//!     Ok(())
97//! }
98//! ```
99//!
100//! Here is another example using `sort` writing into the child process
101//! standard input, capturing the output of the sorted text.
102//!
103//! ```no_run
104//! use tokio::io::AsyncWriteExt;
105//! use tokio::process::Command;
106//!
107//! use std::process::Stdio;
108//!
109//! #[tokio::main]
110//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
111//!     let mut cmd = Command::new("sort");
112//!
113//!     // Specifying that we want pipe both the output and the input.
114//!     // Similarly to capturing the output, by configuring the pipe
115//!     // to stdin it can now be used as an asynchronous writer.
116//!     cmd.stdout(Stdio::piped());
117//!     cmd.stdin(Stdio::piped());
118//!
119//!     let mut child = cmd.spawn().expect("failed to spawn command");
120//!
121//!     // These are the animals we want to sort
122//!     let animals: &[&str] = &["dog", "bird", "frog", "cat", "fish"];
123//!
124//!     let mut stdin = child
125//!         .stdin
126//!         .take()
127//!         .expect("child did not have a handle to stdin");
128//!
129//!     // Write our animals to the child process
130//!     // Note that the behavior of `sort` is to buffer _all input_ before writing any output.
131//!     // In the general sense, it is recommended to write to the child in a separate task as
132//!     // awaiting its exit (or output) to avoid deadlocks (for example, the child tries to write
133//!     // some output but gets stuck waiting on the parent to read from it, meanwhile the parent
134//!     // is stuck waiting to write its input completely before reading the output).
135//!     stdin
136//!         .write(animals.join("\n").as_bytes())
137//!         .await
138//!         .expect("could not write to stdin");
139//!
140//!     // We drop the handle here which signals EOF to the child process.
141//!     // This tells the child process that it there is no more data on the pipe.
142//!     drop(stdin);
143//!
144//!     let op = child.wait_with_output().await?;
145//!
146//!     // Results should come back in sorted order
147//!     assert_eq!(op.stdout, "bird\ncat\ndog\nfish\nfrog\n".as_bytes());
148//!
149//!     Ok(())
150//! }
151//! ```
152//!
153//! With some coordination, we can also pipe the output of one command into
154//! another.
155//!
156//! ```no_run
157//! use tokio::join;
158//! use tokio::process::Command;
159//! use std::process::Stdio;
160//!
161//! #[tokio::main]
162//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
163//!     let mut echo = Command::new("echo")
164//!         .arg("hello world!")
165//!         .stdout(Stdio::piped())
166//!         .spawn()
167//!         .expect("failed to spawn echo");
168//!
169//!     let tr_stdin: Stdio = echo
170//!         .stdout
171//!         .take()
172//!         .unwrap()
173//!         .try_into()
174//!         .expect("failed to convert to Stdio");
175//!
176//!     let tr = Command::new("tr")
177//!         .arg("a-z")
178//!         .arg("A-Z")
179//!         .stdin(tr_stdin)
180//!         .stdout(Stdio::piped())
181//!         .spawn()
182//!         .expect("failed to spawn tr");
183//!
184//!     let (echo_result, tr_output) = join!(echo.wait(), tr.wait_with_output());
185//!
186//!     assert!(echo_result.unwrap().success());
187//!
188//!     let tr_output = tr_output.expect("failed to await tr");
189//!     assert!(tr_output.status.success());
190//!
191//!     assert_eq!(tr_output.stdout, b"HELLO WORLD!\n");
192//!
193//!     Ok(())
194//! }
195//! ```
196//!
197//! # Caveats
198//!
199//! ## Dropping/Cancellation
200//!
201//! Similar to the behavior to the standard library, and unlike the futures
202//! paradigm of dropping-implies-cancellation, a spawned process will, by
203//! default, continue to execute even after the `Child` handle has been dropped.
204//!
205//! The [`Command::kill_on_drop`] method can be used to modify this behavior
206//! and kill the child process if the `Child` wrapper is dropped before it
207//! has exited.
208//!
209//! ## Unix Processes
210//!
211//! On Unix platforms processes must be "reaped" by their parent process after
212//! they have exited in order to release all OS resources. A child process which
213//! has exited, but has not yet been reaped by its parent is considered a "zombie"
214//! process. Such processes continue to count against limits imposed by the system,
215//! and having too many zombie processes present can prevent additional processes
216//! from being spawned.
217//!
218//! The tokio runtime will, on a best-effort basis, attempt to reap and clean up
219//! any process which it has spawned. No additional guarantees are made with regard to
220//! how quickly or how often this procedure will take place.
221//!
222//! It is recommended to avoid dropping a [`Child`] process handle before it has been
223//! fully `await`ed if stricter cleanup guarantees are required.
224//!
225//! [`Command`]: crate::process::Command
226//! [`Command::kill_on_drop`]: crate::process::Command::kill_on_drop
227//! [`Child`]: crate::process::Child
228
229#[path = "unix/mod.rs"]
230#[cfg(unix)]
231mod imp;
232
233#[cfg(unix)]
234pub(crate) mod unix {
235    pub(crate) use super::imp::*;
236}
237
238#[path = "windows.rs"]
239#[cfg(windows)]
240mod imp;
241
242mod kill;
243
244use crate::io::{AsyncRead, AsyncWrite, ReadBuf};
245use crate::process::kill::Kill;
246
247use std::ffi::OsStr;
248use std::future::Future;
249use std::io;
250use std::path::Path;
251use std::pin::Pin;
252use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
253use std::task::Context;
254use std::task::Poll;
255
256#[cfg(unix)]
257use std::os::unix::process::CommandExt;
258#[cfg(windows)]
259use std::os::windows::process::CommandExt;
260
261cfg_windows! {
262    use crate::os::windows::io::{AsRawHandle, RawHandle};
263}
264
265/// This structure mimics the API of [`std::process::Command`] found in the standard library, but
266/// replaces functions that create a process with an asynchronous variant. The main provided
267/// asynchronous functions are [spawn](Command::spawn), [status](Command::status), and
268/// [output](Command::output).
269///
270/// `Command` uses asynchronous versions of some `std` types (for example [`Child`]).
271///
272/// [`std::process::Command`]: std::process::Command
273/// [`Child`]: struct@Child
274#[derive(Debug)]
275pub struct Command {
276    std: StdCommand,
277    kill_on_drop: bool,
278}
279
280pub(crate) struct SpawnedChild {
281    child: imp::Child,
282    stdin: Option<imp::ChildStdio>,
283    stdout: Option<imp::ChildStdio>,
284    stderr: Option<imp::ChildStdio>,
285}
286
287impl Command {
288    /// Constructs a new `Command` for launching the program at
289    /// path `program`, with the following default configuration:
290    ///
291    /// * No arguments to the program
292    /// * Inherit the current process's environment
293    /// * Inherit the current process's working directory
294    /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
295    ///
296    /// Builder methods are provided to change these defaults and
297    /// otherwise configure the process.
298    ///
299    /// If `program` is not an absolute path, the `PATH` will be searched in
300    /// an OS-defined way.
301    ///
302    /// The search path to be used may be controlled by setting the
303    /// `PATH` environment variable on the Command,
304    /// but this has some implementation limitations on Windows
305    /// (see issue [rust-lang/rust#37519]).
306    ///
307    /// # Examples
308    ///
309    /// Basic usage:
310    ///
311    /// ```no_run
312    /// use tokio::process::Command;
313    /// let mut command = Command::new("sh");
314    /// # let _ = command.output(); // assert borrow checker
315    /// ```
316    ///
317    /// [rust-lang/rust#37519]: https://github.com/rust-lang/rust/issues/37519
318    pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
319        Self::from(StdCommand::new(program))
320    }
321
322    /// Cheaply convert to a `&std::process::Command` for places where the type from the standard
323    /// library is expected.
324    pub fn as_std(&self) -> &StdCommand {
325        &self.std
326    }
327
328    /// Adds an argument to pass to the program.
329    ///
330    /// Only one argument can be passed per use. So instead of:
331    ///
332    /// ```no_run
333    /// let mut command = tokio::process::Command::new("sh");
334    /// command.arg("-C /path/to/repo");
335    ///
336    /// # let _ = command.output(); // assert borrow checker
337    /// ```
338    ///
339    /// usage would be:
340    ///
341    /// ```no_run
342    /// let mut command = tokio::process::Command::new("sh");
343    /// command.arg("-C");
344    /// command.arg("/path/to/repo");
345    ///
346    /// # let _ = command.output(); // assert borrow checker
347    /// ```
348    ///
349    /// To pass multiple arguments see [`args`].
350    ///
351    /// [`args`]: method@Self::args
352    ///
353    /// # Examples
354    ///
355    /// Basic usage:
356    ///
357    /// ```no_run
358    /// # async fn test() { // allow using await
359    /// use tokio::process::Command;
360    ///
361    /// let output = Command::new("ls")
362    ///         .arg("-l")
363    ///         .arg("-a")
364    ///         .output().await.unwrap();
365    /// # }
366    ///
367    /// ```
368    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
369        self.std.arg(arg);
370        self
371    }
372
373    /// Adds multiple arguments to pass to the program.
374    ///
375    /// To pass a single argument see [`arg`].
376    ///
377    /// [`arg`]: method@Self::arg
378    ///
379    /// # Examples
380    ///
381    /// Basic usage:
382    ///
383    /// ```no_run
384    /// # async fn test() { // allow using await
385    /// use tokio::process::Command;
386    ///
387    /// let output = Command::new("ls")
388    ///         .args(&["-l", "-a"])
389    ///         .output().await.unwrap();
390    /// # }
391    /// ```
392    pub fn args<I, S>(&mut self, args: I) -> &mut Command
393    where
394        I: IntoIterator<Item = S>,
395        S: AsRef<OsStr>,
396    {
397        self.std.args(args);
398        self
399    }
400
401    cfg_windows! {
402        /// Append literal text to the command line without any quoting or escaping.
403        ///
404        /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
405        /// `CommandLineToArgvW` escaping rules.
406        pub fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut Command {
407            self.std.raw_arg(text_to_append_as_is);
408            self
409        }
410    }
411
412    /// Inserts or updates an environment variable mapping.
413    ///
414    /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
415    /// and case-sensitive on all other platforms.
416    ///
417    /// # Examples
418    ///
419    /// Basic usage:
420    ///
421    /// ```no_run
422    /// # async fn test() { // allow using await
423    /// use tokio::process::Command;
424    ///
425    /// let output = Command::new("ls")
426    ///         .env("PATH", "/bin")
427    ///         .output().await.unwrap();
428    /// # }
429    /// ```
430    pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
431    where
432        K: AsRef<OsStr>,
433        V: AsRef<OsStr>,
434    {
435        self.std.env(key, val);
436        self
437    }
438
439    /// Adds or updates multiple environment variable mappings.
440    ///
441    /// # Examples
442    ///
443    /// Basic usage:
444    ///
445    /// ```no_run
446    /// # async fn test() { // allow using await
447    /// use tokio::process::Command;
448    /// use std::process::{Stdio};
449    /// use std::env;
450    /// use std::collections::HashMap;
451    ///
452    /// let filtered_env : HashMap<String, String> =
453    ///     env::vars().filter(|&(ref k, _)|
454    ///         k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
455    ///     ).collect();
456    ///
457    /// let output = Command::new("printenv")
458    ///         .stdin(Stdio::null())
459    ///         .stdout(Stdio::inherit())
460    ///         .env_clear()
461    ///         .envs(&filtered_env)
462    ///         .output().await.unwrap();
463    /// # }
464    /// ```
465    pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
466    where
467        I: IntoIterator<Item = (K, V)>,
468        K: AsRef<OsStr>,
469        V: AsRef<OsStr>,
470    {
471        self.std.envs(vars);
472        self
473    }
474
475    /// Removes an environment variable mapping.
476    ///
477    /// # Examples
478    ///
479    /// Basic usage:
480    ///
481    /// ```no_run
482    /// # async fn test() { // allow using await
483    /// use tokio::process::Command;
484    ///
485    /// let output = Command::new("ls")
486    ///         .env_remove("PATH")
487    ///         .output().await.unwrap();
488    /// # }
489    /// ```
490    pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
491        self.std.env_remove(key);
492        self
493    }
494
495    /// Clears the entire environment map for the child process.
496    ///
497    /// # Examples
498    ///
499    /// Basic usage:
500    ///
501    /// ```no_run
502    /// # async fn test() { // allow using await
503    /// use tokio::process::Command;
504    ///
505    /// let output = Command::new("ls")
506    ///         .env_clear()
507    ///         .output().await.unwrap();
508    /// # }
509    /// ```
510    pub fn env_clear(&mut self) -> &mut Command {
511        self.std.env_clear();
512        self
513    }
514
515    /// Sets the working directory for the child process.
516    ///
517    /// # Platform-specific behavior
518    ///
519    /// If the program path is relative (e.g., `"./script.sh"`), it's ambiguous
520    /// whether it should be interpreted relative to the parent's working
521    /// directory or relative to `current_dir`. The behavior in this case is
522    /// platform specific and unstable, and it's recommended to use
523    /// [`canonicalize`] to get an absolute program path instead.
524    ///
525    /// [`canonicalize`]: crate::fs::canonicalize()
526    ///
527    /// # Examples
528    ///
529    /// Basic usage:
530    ///
531    /// ```no_run
532    /// # async fn test() { // allow using await
533    /// use tokio::process::Command;
534    ///
535    /// let output = Command::new("ls")
536    ///         .current_dir("/bin")
537    ///         .output().await.unwrap();
538    /// # }
539    /// ```
540    pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
541        self.std.current_dir(dir);
542        self
543    }
544
545    /// Sets configuration for the child process's standard input (stdin) handle.
546    ///
547    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
548    /// defaults to [`piped`] when used with `output`.
549    ///
550    /// [`inherit`]: std::process::Stdio::inherit
551    /// [`piped`]: std::process::Stdio::piped
552    ///
553    /// # Examples
554    ///
555    /// Basic usage:
556    ///
557    /// ```no_run
558    /// # async fn test() { // allow using await
559    /// use std::process::{Stdio};
560    /// use tokio::process::Command;
561    ///
562    /// let output = Command::new("ls")
563    ///         .stdin(Stdio::null())
564    ///         .output().await.unwrap();
565    /// # }
566    /// ```
567    pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
568        self.std.stdin(cfg);
569        self
570    }
571
572    /// Sets configuration for the child process's standard output (stdout) handle.
573    ///
574    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
575    /// defaults to [`piped`] when used with `output`.
576    ///
577    /// [`inherit`]: std::process::Stdio::inherit
578    /// [`piped`]: std::process::Stdio::piped
579    ///
580    /// # Examples
581    ///
582    /// Basic usage:
583    ///
584    /// ```no_run
585    /// # async fn test() { // allow using await
586    /// use tokio::process::Command;
587    /// use std::process::Stdio;
588    ///
589    /// let output = Command::new("ls")
590    ///         .stdout(Stdio::null())
591    ///         .output().await.unwrap();
592    /// # }
593    /// ```
594    pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
595        self.std.stdout(cfg);
596        self
597    }
598
599    /// Sets configuration for the child process's standard error (stderr) handle.
600    ///
601    /// Defaults to [`inherit`] when used with `spawn` or `status`, and
602    /// defaults to [`piped`] when used with `output`.
603    ///
604    /// [`inherit`]: std::process::Stdio::inherit
605    /// [`piped`]: std::process::Stdio::piped
606    ///
607    /// # Examples
608    ///
609    /// Basic usage:
610    ///
611    /// ```no_run
612    /// # async fn test() { // allow using await
613    /// use tokio::process::Command;
614    /// use std::process::{Stdio};
615    ///
616    /// let output = Command::new("ls")
617    ///         .stderr(Stdio::null())
618    ///         .output().await.unwrap();
619    /// # }
620    /// ```
621    pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
622        self.std.stderr(cfg);
623        self
624    }
625
626    /// Controls whether a `kill` operation should be invoked on a spawned child
627    /// process when its corresponding `Child` handle is dropped.
628    ///
629    /// By default, this value is assumed to be `false`, meaning the next spawned
630    /// process will not be killed on drop, similar to the behavior of the standard
631    /// library.
632    ///
633    /// # Caveats
634    ///
635    /// On Unix platforms processes must be "reaped" by their parent process after
636    /// they have exited in order to release all OS resources. A child process which
637    /// has exited, but has not yet been reaped by its parent is considered a "zombie"
638    /// process. Such processes continue to count against limits imposed by the system,
639    /// and having too many zombie processes present can prevent additional processes
640    /// from being spawned.
641    ///
642    /// Although issuing a `kill` signal to the child process is a synchronous
643    /// operation, the resulting zombie process cannot be `.await`ed inside of the
644    /// destructor to avoid blocking other tasks. The tokio runtime will, on a
645    /// best-effort basis, attempt to reap and clean up such processes in the
646    /// background, but no additional guarantees are made with regard to
647    /// how quickly or how often this procedure will take place.
648    ///
649    /// If stronger guarantees are required, it is recommended to avoid dropping
650    /// a [`Child`] handle where possible, and instead utilize `child.wait().await`
651    /// or `child.kill().await` where possible.
652    pub fn kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Command {
653        self.kill_on_drop = kill_on_drop;
654        self
655    }
656
657    cfg_windows! {
658        /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
659        ///
660        /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`.
661        ///
662        /// [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
663        pub fn creation_flags(&mut self, flags: u32) -> &mut Command {
664            self.std.creation_flags(flags);
665            self
666        }
667    }
668
669    /// Sets the child process's user ID. This translates to a
670    /// `setuid` call in the child process. Failure in the `setuid`
671    /// call will cause the spawn to fail.
672    #[cfg(unix)]
673    #[cfg_attr(docsrs, doc(cfg(unix)))]
674    pub fn uid(&mut self, id: u32) -> &mut Command {
675        self.std.uid(id);
676        self
677    }
678
679    /// Similar to `uid` but sets the group ID of the child process. This has
680    /// the same semantics as the `uid` field.
681    #[cfg(unix)]
682    #[cfg_attr(docsrs, doc(cfg(unix)))]
683    pub fn gid(&mut self, id: u32) -> &mut Command {
684        self.std.gid(id);
685        self
686    }
687
688    /// Sets executable argument.
689    ///
690    /// Set the first process argument, `argv[0]`, to something other than the
691    /// default executable path.
692    #[cfg(unix)]
693    #[cfg_attr(docsrs, doc(cfg(unix)))]
694    pub fn arg0<S>(&mut self, arg: S) -> &mut Command
695    where
696        S: AsRef<OsStr>,
697    {
698        self.std.arg0(arg);
699        self
700    }
701
702    /// Schedules a closure to be run just before the `exec` function is
703    /// invoked.
704    ///
705    /// The closure is allowed to return an I/O error whose OS error code will
706    /// be communicated back to the parent and returned as an error from when
707    /// the spawn was requested.
708    ///
709    /// Multiple closures can be registered and they will be called in order of
710    /// their registration. If a closure returns `Err` then no further closures
711    /// will be called and the spawn operation will immediately return with a
712    /// failure.
713    ///
714    /// # Safety
715    ///
716    /// This closure will be run in the context of the child process after a
717    /// `fork`. This primarily means that any modifications made to memory on
718    /// behalf of this closure will **not** be visible to the parent process.
719    /// This is often a very constrained environment where normal operations
720    /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
721    /// other threads perhaps still running when the `fork` was run).
722    ///
723    /// This also means that all resources such as file descriptors and
724    /// memory-mapped regions got duplicated. It is your responsibility to make
725    /// sure that the closure does not violate library invariants by making
726    /// invalid use of these duplicates.
727    ///
728    /// When this closure is run, aspects such as the stdio file descriptors and
729    /// working directory have successfully been changed, so output to these
730    /// locations may not appear where intended.
731    #[cfg(unix)]
732    #[cfg_attr(docsrs, doc(cfg(unix)))]
733    pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Command
734    where
735        F: FnMut() -> io::Result<()> + Send + Sync + 'static,
736    {
737        self.std.pre_exec(f);
738        self
739    }
740
741    /// Sets the process group ID (PGID) of the child process. Equivalent to a
742    /// `setpgid` call in the child process, but may be more efficient.
743    ///
744    /// Process groups determine which processes receive signals.
745    ///
746    /// **Note**: This is an [unstable API][unstable] but will be stabilised once
747    /// tokio's `MSRV` is sufficiently new. See [the documentation on
748    /// unstable features][unstable] for details about using unstable features.
749    ///
750    /// If you want similar behavior without using this unstable feature you can
751    /// create a [`std::process::Command`] and convert that into a
752    /// [`tokio::process::Command`] using the `From` trait.
753    ///
754    /// [unstable]: crate#unstable-features
755    /// [`tokio::process::Command`]: crate::process::Command
756    ///
757    /// ```no_run
758    /// # async fn test() { // allow using await
759    /// use tokio::process::Command;
760    ///
761    /// let output = Command::new("ls")
762    ///         .process_group(0)
763    ///         .output().await.unwrap();
764    /// # }
765    /// ```
766    #[cfg(unix)]
767    #[cfg(tokio_unstable)]
768    #[cfg_attr(docsrs, doc(cfg(all(unix, tokio_unstable))))]
769    pub fn process_group(&mut self, pgroup: i32) -> &mut Command {
770        self.std.process_group(pgroup);
771        self
772    }
773
774    /// Executes the command as a child process, returning a handle to it.
775    ///
776    /// By default, stdin, stdout and stderr are inherited from the parent.
777    ///
778    /// This method will spawn the child process synchronously and return a
779    /// handle to a future-aware child process. The `Child` returned implements
780    /// `Future` itself to acquire the `ExitStatus` of the child, and otherwise
781    /// the `Child` has methods to acquire handles to the stdin, stdout, and
782    /// stderr streams.
783    ///
784    /// All I/O this child does will be associated with the current default
785    /// event loop.
786    ///
787    /// # Examples
788    ///
789    /// Basic usage:
790    ///
791    /// ```no_run
792    /// use tokio::process::Command;
793    ///
794    /// async fn run_ls() -> std::process::ExitStatus {
795    ///     Command::new("ls")
796    ///         .spawn()
797    ///         .expect("ls command failed to start")
798    ///         .wait()
799    ///         .await
800    ///         .expect("ls command failed to run")
801    /// }
802    /// ```
803    ///
804    /// # Caveats
805    ///
806    /// ## Dropping/Cancellation
807    ///
808    /// Similar to the behavior to the standard library, and unlike the futures
809    /// paradigm of dropping-implies-cancellation, a spawned process will, by
810    /// default, continue to execute even after the `Child` handle has been dropped.
811    ///
812    /// The [`Command::kill_on_drop`] method can be used to modify this behavior
813    /// and kill the child process if the `Child` wrapper is dropped before it
814    /// has exited.
815    ///
816    /// ## Unix Processes
817    ///
818    /// On Unix platforms processes must be "reaped" by their parent process after
819    /// they have exited in order to release all OS resources. A child process which
820    /// has exited, but has not yet been reaped by its parent is considered a "zombie"
821    /// process. Such processes continue to count against limits imposed by the system,
822    /// and having too many zombie processes present can prevent additional processes
823    /// from being spawned.
824    ///
825    /// The tokio runtime will, on a best-effort basis, attempt to reap and clean up
826    /// any process which it has spawned. No additional guarantees are made with regard to
827    /// how quickly or how often this procedure will take place.
828    ///
829    /// It is recommended to avoid dropping a [`Child`] process handle before it has been
830    /// fully `await`ed if stricter cleanup guarantees are required.
831    ///
832    /// [`Command`]: crate::process::Command
833    /// [`Command::kill_on_drop`]: crate::process::Command::kill_on_drop
834    /// [`Child`]: crate::process::Child
835    ///
836    /// # Errors
837    ///
838    /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
839    /// if the system process limit is reached (which includes other applications
840    /// running on the system).
841    pub fn spawn(&mut self) -> io::Result<Child> {
842        imp::spawn_child(&mut self.std).map(|spawned_child| Child {
843            child: FusedChild::Child(ChildDropGuard {
844                inner: spawned_child.child,
845                kill_on_drop: self.kill_on_drop,
846            }),
847            stdin: spawned_child.stdin.map(|inner| ChildStdin { inner }),
848            stdout: spawned_child.stdout.map(|inner| ChildStdout { inner }),
849            stderr: spawned_child.stderr.map(|inner| ChildStderr { inner }),
850        })
851    }
852
853    /// Executes the command as a child process, waiting for it to finish and
854    /// collecting its exit status.
855    ///
856    /// By default, stdin, stdout and stderr are inherited from the parent.
857    /// If any input/output handles are set to a pipe then they will be immediately
858    /// closed after the child is spawned.
859    ///
860    /// All I/O this child does will be associated with the current default
861    /// event loop.
862    ///
863    /// The destructor of the future returned by this function will kill
864    /// the child if [`kill_on_drop`] is set to true.
865    ///
866    /// [`kill_on_drop`]: fn@Self::kill_on_drop
867    ///
868    /// # Errors
869    ///
870    /// This future will return an error if the child process cannot be spawned
871    /// or if there is an error while awaiting its status.
872    ///
873    /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
874    /// if the system process limit is reached (which includes other applications
875    /// running on the system).
876    ///
877    /// # Examples
878    ///
879    /// Basic usage:
880    ///
881    /// ```no_run
882    /// use tokio::process::Command;
883    ///
884    /// async fn run_ls() -> std::process::ExitStatus {
885    ///     Command::new("ls")
886    ///         .status()
887    ///         .await
888    ///         .expect("ls command failed to run")
889    /// }
890    /// ```
891    pub fn status(&mut self) -> impl Future<Output = io::Result<ExitStatus>> {
892        let child = self.spawn();
893
894        async {
895            let mut child = child?;
896
897            // Ensure we close any stdio handles so we can't deadlock
898            // waiting on the child which may be waiting to read/write
899            // to a pipe we're holding.
900            child.stdin.take();
901            child.stdout.take();
902            child.stderr.take();
903
904            child.wait().await
905        }
906    }
907
908    /// Executes the command as a child process, waiting for it to finish and
909    /// collecting all of its output.
910    ///
911    /// > **Note**: this method, unlike the standard library, will
912    /// > unconditionally configure the stdout/stderr handles to be pipes, even
913    /// > if they have been previously configured. If this is not desired then
914    /// > the `spawn` method should be used in combination with the
915    /// > `wait_with_output` method on child.
916    ///
917    /// This method will return a future representing the collection of the
918    /// child process's stdout/stderr. It will resolve to
919    /// the `Output` type in the standard library, containing `stdout` and
920    /// `stderr` as `Vec<u8>` along with an `ExitStatus` representing how the
921    /// process exited.
922    ///
923    /// All I/O this child does will be associated with the current default
924    /// event loop.
925    ///
926    /// The destructor of the future returned by this function will kill
927    /// the child if [`kill_on_drop`] is set to true.
928    ///
929    /// [`kill_on_drop`]: fn@Self::kill_on_drop
930    ///
931    /// # Errors
932    ///
933    /// This future will return an error if the child process cannot be spawned
934    /// or if there is an error while awaiting its status.
935    ///
936    /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
937    /// if the system process limit is reached (which includes other applications
938    /// running on the system).
939    /// # Examples
940    ///
941    /// Basic usage:
942    ///
943    /// ```no_run
944    /// use tokio::process::Command;
945    ///
946    /// async fn run_ls() {
947    ///     let output: std::process::Output = Command::new("ls")
948    ///         .output()
949    ///         .await
950    ///         .expect("ls command failed to run");
951    ///     println!("stderr of ls: {:?}", output.stderr);
952    /// }
953    /// ```
954    pub fn output(&mut self) -> impl Future<Output = io::Result<Output>> {
955        self.std.stdout(Stdio::piped());
956        self.std.stderr(Stdio::piped());
957
958        let child = self.spawn();
959
960        async { child?.wait_with_output().await }
961    }
962}
963
964impl From<StdCommand> for Command {
965    fn from(std: StdCommand) -> Command {
966        Command {
967            std,
968            kill_on_drop: false,
969        }
970    }
971}
972
973/// A drop guard which can ensure the child process is killed on drop if specified.
974#[derive(Debug)]
975struct ChildDropGuard<T: Kill> {
976    inner: T,
977    kill_on_drop: bool,
978}
979
980impl<T: Kill> Kill for ChildDropGuard<T> {
981    fn kill(&mut self) -> io::Result<()> {
982        let ret = self.inner.kill();
983
984        if ret.is_ok() {
985            self.kill_on_drop = false;
986        }
987
988        ret
989    }
990}
991
992impl<T: Kill> Drop for ChildDropGuard<T> {
993    fn drop(&mut self) {
994        if self.kill_on_drop {
995            drop(self.kill());
996        }
997    }
998}
999
1000impl<T, E, F> Future for ChildDropGuard<F>
1001where
1002    F: Future<Output = Result<T, E>> + Kill + Unpin,
1003{
1004    type Output = Result<T, E>;
1005
1006    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
1007        ready!(crate::trace::trace_leaf(cx));
1008        // Keep track of task budget
1009        let coop = ready!(crate::runtime::coop::poll_proceed(cx));
1010
1011        let ret = Pin::new(&mut self.inner).poll(cx);
1012
1013        if let Poll::Ready(Ok(_)) = ret {
1014            // Avoid the overhead of trying to kill a reaped process
1015            self.kill_on_drop = false;
1016        }
1017
1018        if ret.is_ready() {
1019            coop.made_progress();
1020        }
1021
1022        ret
1023    }
1024}
1025
1026/// Keeps track of the exit status of a child process without worrying about
1027/// polling the underlying futures even after they have completed.
1028#[derive(Debug)]
1029enum FusedChild {
1030    Child(ChildDropGuard<imp::Child>),
1031    Done(ExitStatus),
1032}
1033
1034/// Representation of a child process spawned onto an event loop.
1035///
1036/// # Caveats
1037/// Similar to the behavior to the standard library, and unlike the futures
1038/// paradigm of dropping-implies-cancellation, a spawned process will, by
1039/// default, continue to execute even after the `Child` handle has been dropped.
1040///
1041/// The `Command::kill_on_drop` method can be used to modify this behavior
1042/// and kill the child process if the `Child` wrapper is dropped before it
1043/// has exited.
1044#[derive(Debug)]
1045pub struct Child {
1046    child: FusedChild,
1047
1048    /// The handle for writing to the child's standard input (stdin), if it has
1049    /// been captured. To avoid partially moving the `child` and thus blocking
1050    /// yourself from calling functions on `child` while using `stdin`, you might
1051    /// find it helpful to do:
1052    ///
1053    /// ```no_run
1054    /// # let mut child = tokio::process::Command::new("echo").spawn().unwrap();
1055    /// let stdin = child.stdin.take().unwrap();
1056    /// ```
1057    pub stdin: Option<ChildStdin>,
1058
1059    /// The handle for reading from the child's standard output (stdout), if it
1060    /// has been captured. You might find it helpful to do
1061    ///
1062    /// ```no_run
1063    /// # let mut child = tokio::process::Command::new("echo").spawn().unwrap();
1064    /// let stdout = child.stdout.take().unwrap();
1065    /// ```
1066    ///
1067    /// to avoid partially moving the `child` and thus blocking yourself from calling
1068    /// functions on `child` while using `stdout`.
1069    pub stdout: Option<ChildStdout>,
1070
1071    /// The handle for reading from the child's standard error (stderr), if it
1072    /// has been captured. You might find it helpful to do
1073    ///
1074    /// ```no_run
1075    /// # let mut child = tokio::process::Command::new("echo").spawn().unwrap();
1076    /// let stderr = child.stderr.take().unwrap();
1077    /// ```
1078    ///
1079    /// to avoid partially moving the `child` and thus blocking yourself from calling
1080    /// functions on `child` while using `stderr`.
1081    pub stderr: Option<ChildStderr>,
1082}
1083
1084impl Child {
1085    /// Returns the OS-assigned process identifier associated with this child
1086    /// while it is still running.
1087    ///
1088    /// Once the child has been polled to completion this will return `None`.
1089    /// This is done to avoid confusion on platforms like Unix where the OS
1090    /// identifier could be reused once the process has completed.
1091    pub fn id(&self) -> Option<u32> {
1092        match &self.child {
1093            FusedChild::Child(child) => Some(child.inner.id()),
1094            FusedChild::Done(_) => None,
1095        }
1096    }
1097
1098    cfg_windows! {
1099        /// Extracts the raw handle of the process associated with this child while
1100        /// it is still running. Returns `None` if the child has exited.
1101        pub fn raw_handle(&self) -> Option<RawHandle> {
1102            match &self.child {
1103                FusedChild::Child(c) => Some(c.inner.as_raw_handle()),
1104                FusedChild::Done(_) => None,
1105            }
1106        }
1107    }
1108
1109    /// Attempts to force the child to exit, but does not wait for the request
1110    /// to take effect.
1111    ///
1112    /// On Unix platforms, this is the equivalent to sending a `SIGKILL`. Note
1113    /// that on Unix platforms it is possible for a zombie process to remain
1114    /// after a kill is sent; to avoid this, the caller should ensure that either
1115    /// `child.wait().await` or `child.try_wait()` is invoked successfully.
1116    pub fn start_kill(&mut self) -> io::Result<()> {
1117        match &mut self.child {
1118            FusedChild::Child(child) => child.kill(),
1119            FusedChild::Done(_) => Err(io::Error::new(
1120                io::ErrorKind::InvalidInput,
1121                "invalid argument: can't kill an exited process",
1122            )),
1123        }
1124    }
1125
1126    /// Forces the child to exit.
1127    ///
1128    /// This is equivalent to sending a `SIGKILL` on unix platforms.
1129    ///
1130    /// If the child has to be killed remotely, it is possible to do it using
1131    /// a combination of the select! macro and a `oneshot` channel. In the following
1132    /// example, the child will run until completion unless a message is sent on
1133    /// the `oneshot` channel. If that happens, the child is killed immediately
1134    /// using the `.kill()` method.
1135    ///
1136    /// ```no_run
1137    /// use tokio::process::Command;
1138    /// use tokio::sync::oneshot::channel;
1139    ///
1140    /// #[tokio::main]
1141    /// async fn main() {
1142    ///     let (send, recv) = channel::<()>();
1143    ///     let mut child = Command::new("sleep").arg("1").spawn().unwrap();
1144    ///     tokio::spawn(async move { send.send(()) });
1145    ///     tokio::select! {
1146    ///         _ = child.wait() => {}
1147    ///         _ = recv => child.kill().await.expect("kill failed"),
1148    ///     }
1149    /// }
1150    /// ```
1151    pub async fn kill(&mut self) -> io::Result<()> {
1152        self.start_kill()?;
1153        self.wait().await?;
1154        Ok(())
1155    }
1156
1157    /// Waits for the child to exit completely, returning the status that it
1158    /// exited with. This function will continue to have the same return value
1159    /// after it has been called at least once.
1160    ///
1161    /// The stdin handle to the child process, if any, will be closed
1162    /// before waiting. This helps avoid deadlock: it ensures that the
1163    /// child does not block waiting for input from the parent, while
1164    /// the parent waits for the child to exit.
1165    ///
1166    /// If the caller wishes to explicitly control when the child's stdin
1167    /// handle is closed, they may `.take()` it before calling `.wait()`:
1168    ///
1169    /// # Cancel safety
1170    ///
1171    /// This function is cancel safe.
1172    ///
1173    /// ```
1174    /// # #[cfg(not(unix))]fn main(){}
1175    /// # #[cfg(unix)]
1176    /// use tokio::io::AsyncWriteExt;
1177    /// # #[cfg(unix)]
1178    /// use tokio::process::Command;
1179    /// # #[cfg(unix)]
1180    /// use std::process::Stdio;
1181    ///
1182    /// # #[cfg(unix)]
1183    /// #[tokio::main]
1184    /// async fn main() {
1185    ///     let mut child = Command::new("cat")
1186    ///         .stdin(Stdio::piped())
1187    ///         .spawn()
1188    ///         .unwrap();
1189    ///
1190    ///     let mut stdin = child.stdin.take().unwrap();
1191    ///     tokio::spawn(async move {
1192    ///         // do something with stdin here...
1193    ///         stdin.write_all(b"hello world\n").await.unwrap();
1194    ///
1195    ///         // then drop when finished
1196    ///         drop(stdin);
1197    ///     });
1198    ///
1199    ///     // wait for the process to complete
1200    ///     let _ = child.wait().await;
1201    /// }
1202    /// ```
1203    pub async fn wait(&mut self) -> io::Result<ExitStatus> {
1204        // Ensure stdin is closed so the child isn't stuck waiting on
1205        // input while the parent is waiting for it to exit.
1206        drop(self.stdin.take());
1207
1208        match &mut self.child {
1209            FusedChild::Done(exit) => Ok(*exit),
1210            FusedChild::Child(child) => {
1211                let ret = child.await;
1212
1213                if let Ok(exit) = ret {
1214                    self.child = FusedChild::Done(exit);
1215                }
1216
1217                ret
1218            }
1219        }
1220    }
1221
1222    /// Attempts to collect the exit status of the child if it has already
1223    /// exited.
1224    ///
1225    /// This function will not block the calling thread and will only
1226    /// check to see if the child process has exited or not. If the child has
1227    /// exited then on Unix the process ID is reaped. This function is
1228    /// guaranteed to repeatedly return a successful exit status so long as the
1229    /// child has already exited.
1230    ///
1231    /// If the child has exited, then `Ok(Some(status))` is returned. If the
1232    /// exit status is not available at this time then `Ok(None)` is returned.
1233    /// If an error occurs, then that error is returned.
1234    ///
1235    /// Note that unlike `wait`, this function will not attempt to drop stdin,
1236    /// nor will it wake the current task if the child exits.
1237    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
1238        match &mut self.child {
1239            FusedChild::Done(exit) => Ok(Some(*exit)),
1240            FusedChild::Child(guard) => {
1241                let ret = guard.inner.try_wait();
1242
1243                if let Ok(Some(exit)) = ret {
1244                    // Avoid the overhead of trying to kill a reaped process
1245                    guard.kill_on_drop = false;
1246                    self.child = FusedChild::Done(exit);
1247                }
1248
1249                ret
1250            }
1251        }
1252    }
1253
1254    /// Returns a future that will resolve to an `Output`, containing the exit
1255    /// status, stdout, and stderr of the child process.
1256    ///
1257    /// The returned future will simultaneously waits for the child to exit and
1258    /// collect all remaining output on the stdout/stderr handles, returning an
1259    /// `Output` instance.
1260    ///
1261    /// The stdin handle to the child process, if any, will be closed before
1262    /// waiting. This helps avoid deadlock: it ensures that the child does not
1263    /// block waiting for input from the parent, while the parent waits for the
1264    /// child to exit.
1265    ///
1266    /// By default, stdin, stdout and stderr are inherited from the parent. In
1267    /// order to capture the output into this `Output` it is necessary to create
1268    /// new pipes between parent and child. Use `stdout(Stdio::piped())` or
1269    /// `stderr(Stdio::piped())`, respectively, when creating a `Command`.
1270    pub async fn wait_with_output(mut self) -> io::Result<Output> {
1271        use crate::future::try_join3;
1272
1273        async fn read_to_end<A: AsyncRead + Unpin>(io: &mut Option<A>) -> io::Result<Vec<u8>> {
1274            let mut vec = Vec::new();
1275            if let Some(io) = io.as_mut() {
1276                crate::io::util::read_to_end(io, &mut vec).await?;
1277            }
1278            Ok(vec)
1279        }
1280
1281        let mut stdout_pipe = self.stdout.take();
1282        let mut stderr_pipe = self.stderr.take();
1283
1284        let stdout_fut = read_to_end(&mut stdout_pipe);
1285        let stderr_fut = read_to_end(&mut stderr_pipe);
1286
1287        let (status, stdout, stderr) = try_join3(self.wait(), stdout_fut, stderr_fut).await?;
1288
1289        // Drop happens after `try_join` due to <https://github.com/tokio-rs/tokio/issues/4309>
1290        drop(stdout_pipe);
1291        drop(stderr_pipe);
1292
1293        Ok(Output {
1294            status,
1295            stdout,
1296            stderr,
1297        })
1298    }
1299}
1300
1301/// The standard input stream for spawned children.
1302///
1303/// This type implements the `AsyncWrite` trait to pass data to the stdin handle of
1304/// handle of a child process asynchronously.
1305#[derive(Debug)]
1306pub struct ChildStdin {
1307    inner: imp::ChildStdio,
1308}
1309
1310/// The standard output stream for spawned children.
1311///
1312/// This type implements the `AsyncRead` trait to read data from the stdout
1313/// handle of a child process asynchronously.
1314#[derive(Debug)]
1315pub struct ChildStdout {
1316    inner: imp::ChildStdio,
1317}
1318
1319/// The standard error stream for spawned children.
1320///
1321/// This type implements the `AsyncRead` trait to read data from the stderr
1322/// handle of a child process asynchronously.
1323#[derive(Debug)]
1324pub struct ChildStderr {
1325    inner: imp::ChildStdio,
1326}
1327
1328impl ChildStdin {
1329    /// Creates an asynchronous `ChildStdin` from a synchronous one.
1330    ///
1331    /// # Errors
1332    ///
1333    /// This method may fail if an error is encountered when setting the pipe to
1334    /// non-blocking mode, or when registering the pipe with the runtime's IO
1335    /// driver.
1336    pub fn from_std(inner: std::process::ChildStdin) -> io::Result<Self> {
1337        Ok(Self {
1338            inner: imp::stdio(inner)?,
1339        })
1340    }
1341}
1342
1343impl ChildStdout {
1344    /// Creates an asynchronous `ChildStdout` from a synchronous one.
1345    ///
1346    /// # Errors
1347    ///
1348    /// This method may fail if an error is encountered when setting the pipe to
1349    /// non-blocking mode, or when registering the pipe with the runtime's IO
1350    /// driver.
1351    pub fn from_std(inner: std::process::ChildStdout) -> io::Result<Self> {
1352        Ok(Self {
1353            inner: imp::stdio(inner)?,
1354        })
1355    }
1356}
1357
1358impl ChildStderr {
1359    /// Creates an asynchronous `ChildStderr` from a synchronous one.
1360    ///
1361    /// # Errors
1362    ///
1363    /// This method may fail if an error is encountered when setting the pipe to
1364    /// non-blocking mode, or when registering the pipe with the runtime's IO
1365    /// driver.
1366    pub fn from_std(inner: std::process::ChildStderr) -> io::Result<Self> {
1367        Ok(Self {
1368            inner: imp::stdio(inner)?,
1369        })
1370    }
1371}
1372
1373impl AsyncWrite for ChildStdin {
1374    fn poll_write(
1375        mut self: Pin<&mut Self>,
1376        cx: &mut Context<'_>,
1377        buf: &[u8],
1378    ) -> Poll<io::Result<usize>> {
1379        Pin::new(&mut self.inner).poll_write(cx, buf)
1380    }
1381
1382    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
1383        Pin::new(&mut self.inner).poll_flush(cx)
1384    }
1385
1386    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
1387        Pin::new(&mut self.inner).poll_shutdown(cx)
1388    }
1389
1390    fn poll_write_vectored(
1391        mut self: Pin<&mut Self>,
1392        cx: &mut Context<'_>,
1393        bufs: &[io::IoSlice<'_>],
1394    ) -> Poll<Result<usize, io::Error>> {
1395        Pin::new(&mut self.inner).poll_write_vectored(cx, bufs)
1396    }
1397
1398    fn is_write_vectored(&self) -> bool {
1399        self.inner.is_write_vectored()
1400    }
1401}
1402
1403impl AsyncRead for ChildStdout {
1404    fn poll_read(
1405        mut self: Pin<&mut Self>,
1406        cx: &mut Context<'_>,
1407        buf: &mut ReadBuf<'_>,
1408    ) -> Poll<io::Result<()>> {
1409        Pin::new(&mut self.inner).poll_read(cx, buf)
1410    }
1411}
1412
1413impl AsyncRead for ChildStderr {
1414    fn poll_read(
1415        mut self: Pin<&mut Self>,
1416        cx: &mut Context<'_>,
1417        buf: &mut ReadBuf<'_>,
1418    ) -> Poll<io::Result<()>> {
1419        Pin::new(&mut self.inner).poll_read(cx, buf)
1420    }
1421}
1422
1423impl TryInto<Stdio> for ChildStdin {
1424    type Error = io::Error;
1425
1426    fn try_into(self) -> Result<Stdio, Self::Error> {
1427        imp::convert_to_stdio(self.inner)
1428    }
1429}
1430
1431impl TryInto<Stdio> for ChildStdout {
1432    type Error = io::Error;
1433
1434    fn try_into(self) -> Result<Stdio, Self::Error> {
1435        imp::convert_to_stdio(self.inner)
1436    }
1437}
1438
1439impl TryInto<Stdio> for ChildStderr {
1440    type Error = io::Error;
1441
1442    fn try_into(self) -> Result<Stdio, Self::Error> {
1443        imp::convert_to_stdio(self.inner)
1444    }
1445}
1446
1447#[cfg(unix)]
1448#[cfg_attr(docsrs, doc(cfg(unix)))]
1449mod sys {
1450    use std::{
1451        io,
1452        os::unix::io::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd},
1453    };
1454
1455    use super::{ChildStderr, ChildStdin, ChildStdout};
1456
1457    macro_rules! impl_traits {
1458        ($type:ty) => {
1459            impl $type {
1460                /// Convert into [`OwnedFd`].
1461                pub fn into_owned_fd(self) -> io::Result<OwnedFd> {
1462                    self.inner.into_owned_fd()
1463                }
1464            }
1465
1466            impl AsRawFd for $type {
1467                fn as_raw_fd(&self) -> RawFd {
1468                    self.inner.as_raw_fd()
1469                }
1470            }
1471
1472            impl AsFd for $type {
1473                fn as_fd(&self) -> BorrowedFd<'_> {
1474                    unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
1475                }
1476            }
1477        };
1478    }
1479
1480    impl_traits!(ChildStdin);
1481    impl_traits!(ChildStdout);
1482    impl_traits!(ChildStderr);
1483}
1484
1485#[cfg(any(windows, docsrs))]
1486#[cfg_attr(docsrs, doc(cfg(windows)))]
1487mod windows {
1488    use super::*;
1489    use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, OwnedHandle, RawHandle};
1490
1491    #[cfg(not(docsrs))]
1492    macro_rules! impl_traits {
1493        ($type:ty) => {
1494            impl $type {
1495                /// Convert into [`OwnedHandle`].
1496                pub fn into_owned_handle(self) -> io::Result<OwnedHandle> {
1497                    self.inner.into_owned_handle()
1498                }
1499            }
1500
1501            impl AsRawHandle for $type {
1502                fn as_raw_handle(&self) -> RawHandle {
1503                    self.inner.as_raw_handle()
1504                }
1505            }
1506
1507            impl AsHandle for $type {
1508                fn as_handle(&self) -> BorrowedHandle<'_> {
1509                    unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
1510                }
1511            }
1512        };
1513    }
1514
1515    #[cfg(docsrs)]
1516    macro_rules! impl_traits {
1517        ($type:ty) => {
1518            impl $type {
1519                /// Convert into [`OwnedHandle`].
1520                pub fn into_owned_handle(self) -> io::Result<OwnedHandle> {
1521                    todo!("For doc generation only")
1522                }
1523            }
1524
1525            impl AsRawHandle for $type {
1526                fn as_raw_handle(&self) -> RawHandle {
1527                    todo!("For doc generation only")
1528                }
1529            }
1530
1531            impl AsHandle for $type {
1532                fn as_handle(&self) -> BorrowedHandle<'_> {
1533                    todo!("For doc generation only")
1534                }
1535            }
1536        };
1537    }
1538
1539    impl_traits!(ChildStdin);
1540    impl_traits!(ChildStdout);
1541    impl_traits!(ChildStderr);
1542}
1543
1544#[cfg(all(test, not(loom)))]
1545mod test {
1546    use super::kill::Kill;
1547    use super::ChildDropGuard;
1548
1549    use futures::future::FutureExt;
1550    use std::future::Future;
1551    use std::io;
1552    use std::pin::Pin;
1553    use std::task::{Context, Poll};
1554
1555    struct Mock {
1556        num_kills: usize,
1557        num_polls: usize,
1558        poll_result: Poll<Result<(), ()>>,
1559    }
1560
1561    impl Mock {
1562        fn new() -> Self {
1563            Self::with_result(Poll::Pending)
1564        }
1565
1566        fn with_result(result: Poll<Result<(), ()>>) -> Self {
1567            Self {
1568                num_kills: 0,
1569                num_polls: 0,
1570                poll_result: result,
1571            }
1572        }
1573    }
1574
1575    impl Kill for Mock {
1576        fn kill(&mut self) -> io::Result<()> {
1577            self.num_kills += 1;
1578            Ok(())
1579        }
1580    }
1581
1582    impl Future for Mock {
1583        type Output = Result<(), ()>;
1584
1585        fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
1586            let inner = Pin::get_mut(self);
1587            inner.num_polls += 1;
1588            inner.poll_result
1589        }
1590    }
1591
1592    #[test]
1593    fn kills_on_drop_if_specified() {
1594        let mut mock = Mock::new();
1595
1596        {
1597            let guard = ChildDropGuard {
1598                inner: &mut mock,
1599                kill_on_drop: true,
1600            };
1601            drop(guard);
1602        }
1603
1604        assert_eq!(1, mock.num_kills);
1605        assert_eq!(0, mock.num_polls);
1606    }
1607
1608    #[test]
1609    fn no_kill_on_drop_by_default() {
1610        let mut mock = Mock::new();
1611
1612        {
1613            let guard = ChildDropGuard {
1614                inner: &mut mock,
1615                kill_on_drop: false,
1616            };
1617            drop(guard);
1618        }
1619
1620        assert_eq!(0, mock.num_kills);
1621        assert_eq!(0, mock.num_polls);
1622    }
1623
1624    #[test]
1625    fn no_kill_if_already_killed() {
1626        let mut mock = Mock::new();
1627
1628        {
1629            let mut guard = ChildDropGuard {
1630                inner: &mut mock,
1631                kill_on_drop: true,
1632            };
1633            let _ = guard.kill();
1634            drop(guard);
1635        }
1636
1637        assert_eq!(1, mock.num_kills);
1638        assert_eq!(0, mock.num_polls);
1639    }
1640
1641    #[test]
1642    fn no_kill_if_reaped() {
1643        let mut mock_pending = Mock::with_result(Poll::Pending);
1644        let mut mock_reaped = Mock::with_result(Poll::Ready(Ok(())));
1645        let mut mock_err = Mock::with_result(Poll::Ready(Err(())));
1646
1647        let waker = futures::task::noop_waker();
1648        let mut context = Context::from_waker(&waker);
1649        {
1650            let mut guard = ChildDropGuard {
1651                inner: &mut mock_pending,
1652                kill_on_drop: true,
1653            };
1654            let _ = guard.poll_unpin(&mut context);
1655
1656            let mut guard = ChildDropGuard {
1657                inner: &mut mock_reaped,
1658                kill_on_drop: true,
1659            };
1660            let _ = guard.poll_unpin(&mut context);
1661
1662            let mut guard = ChildDropGuard {
1663                inner: &mut mock_err,
1664                kill_on_drop: true,
1665            };
1666            let _ = guard.poll_unpin(&mut context);
1667        }
1668
1669        assert_eq!(1, mock_pending.num_kills);
1670        assert_eq!(1, mock_pending.num_polls);
1671
1672        assert_eq!(0, mock_reaped.num_kills);
1673        assert_eq!(1, mock_reaped.num_polls);
1674
1675        assert_eq!(1, mock_err.num_kills);
1676        assert_eq!(1, mock_err.num_polls);
1677    }
1678}