• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //! With some coordination, we can also pipe the output of one command into
101 //! another.
102 //!
103 //! ```no_run
104 //! use tokio::join;
105 //! use tokio::process::Command;
106 //! use std::convert::TryInto;
107 //! use std::process::Stdio;
108 //!
109 //! #[tokio::main]
110 //! async fn main() -> Result<(), Box<dyn std::error::Error>> {
111 //!     let mut echo = Command::new("echo")
112 //!         .arg("hello world!")
113 //!         .stdout(Stdio::piped())
114 //!         .spawn()
115 //!         .expect("failed to spawn echo");
116 //!
117 //!     let tr_stdin: Stdio = echo
118 //!         .stdout
119 //!         .take()
120 //!         .unwrap()
121 //!         .try_into()
122 //!         .expect("failed to convert to Stdio");
123 //!
124 //!     let tr = Command::new("tr")
125 //!         .arg("a-z")
126 //!         .arg("A-Z")
127 //!         .stdin(tr_stdin)
128 //!         .stdout(Stdio::piped())
129 //!         .spawn()
130 //!         .expect("failed to spawn tr");
131 //!
132 //!     let (echo_result, tr_output) = join!(echo.wait(), tr.wait_with_output());
133 //!
134 //!     assert!(echo_result.unwrap().success());
135 //!
136 //!     let tr_output = tr_output.expect("failed to await tr");
137 //!     assert!(tr_output.status.success());
138 //!
139 //!     assert_eq!(tr_output.stdout, b"HELLO WORLD!\n");
140 //!
141 //!     Ok(())
142 //! }
143 //! ```
144 //!
145 //! # Caveats
146 //!
147 //! ## Dropping/Cancellation
148 //!
149 //! Similar to the behavior to the standard library, and unlike the futures
150 //! paradigm of dropping-implies-cancellation, a spawned process will, by
151 //! default, continue to execute even after the `Child` handle has been dropped.
152 //!
153 //! The [`Command::kill_on_drop`] method can be used to modify this behavior
154 //! and kill the child process if the `Child` wrapper is dropped before it
155 //! has exited.
156 //!
157 //! ## Unix Processes
158 //!
159 //! On Unix platforms processes must be "reaped" by their parent process after
160 //! they have exited in order to release all OS resources. A child process which
161 //! has exited, but has not yet been reaped by its parent is considered a "zombie"
162 //! process. Such processes continue to count against limits imposed by the system,
163 //! and having too many zombie processes present can prevent additional processes
164 //! from being spawned.
165 //!
166 //! The tokio runtime will, on a best-effort basis, attempt to reap and clean up
167 //! any process which it has spawned. No additional guarantees are made with regards
168 //! how quickly or how often this procedure will take place.
169 //!
170 //! It is recommended to avoid dropping a [`Child`] process handle before it has been
171 //! fully `await`ed if stricter cleanup guarantees are required.
172 //!
173 //! [`Command`]: crate::process::Command
174 //! [`Command::kill_on_drop`]: crate::process::Command::kill_on_drop
175 //! [`Child`]: crate::process::Child
176 
177 #[path = "unix/mod.rs"]
178 #[cfg(unix)]
179 mod imp;
180 
181 #[cfg(unix)]
182 pub(crate) mod unix {
183     pub(crate) use super::imp::*;
184 }
185 
186 #[path = "windows.rs"]
187 #[cfg(windows)]
188 mod imp;
189 
190 mod kill;
191 
192 use crate::io::{AsyncRead, AsyncWrite, ReadBuf};
193 use crate::process::kill::Kill;
194 
195 use std::convert::TryInto;
196 use std::ffi::OsStr;
197 use std::future::Future;
198 use std::io;
199 #[cfg(unix)]
200 use std::os::unix::process::CommandExt;
201 #[cfg(windows)]
202 use std::os::windows::process::CommandExt;
203 use std::path::Path;
204 use std::pin::Pin;
205 use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
206 use std::task::Context;
207 use std::task::Poll;
208 
209 /// This structure mimics the API of [`std::process::Command`] found in the standard library, but
210 /// replaces functions that create a process with an asynchronous variant. The main provided
211 /// asynchronous functions are [spawn](Command::spawn), [status](Command::status), and
212 /// [output](Command::output).
213 ///
214 /// `Command` uses asynchronous versions of some `std` types (for example [`Child`]).
215 ///
216 /// [`std::process::Command`]: std::process::Command
217 /// [`Child`]: struct@Child
218 #[derive(Debug)]
219 pub struct Command {
220     std: StdCommand,
221     kill_on_drop: bool,
222 }
223 
224 pub(crate) struct SpawnedChild {
225     child: imp::Child,
226     stdin: Option<imp::ChildStdin>,
227     stdout: Option<imp::ChildStdout>,
228     stderr: Option<imp::ChildStderr>,
229 }
230 
231 impl Command {
232     /// Constructs a new `Command` for launching the program at
233     /// path `program`, with the following default configuration:
234     ///
235     /// * No arguments to the program
236     /// * Inherit the current process's environment
237     /// * Inherit the current process's working directory
238     /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
239     ///
240     /// Builder methods are provided to change these defaults and
241     /// otherwise configure the process.
242     ///
243     /// If `program` is not an absolute path, the `PATH` will be searched in
244     /// an OS-defined way.
245     ///
246     /// The search path to be used may be controlled by setting the
247     /// `PATH` environment variable on the Command,
248     /// but this has some implementation limitations on Windows
249     /// (see issue [rust-lang/rust#37519]).
250     ///
251     /// # Examples
252     ///
253     /// Basic usage:
254     ///
255     /// ```no_run
256     /// use tokio::process::Command;
257     /// let command = Command::new("sh");
258     /// ```
259     ///
260     /// [rust-lang/rust#37519]: https://github.com/rust-lang/rust/issues/37519
new<S: AsRef<OsStr>>(program: S) -> Command261     pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
262         Self::from(StdCommand::new(program))
263     }
264 
265     /// Adds an argument to pass to the program.
266     ///
267     /// Only one argument can be passed per use. So instead of:
268     ///
269     /// ```no_run
270     /// tokio::process::Command::new("sh")
271     ///   .arg("-C /path/to/repo");
272     /// ```
273     ///
274     /// usage would be:
275     ///
276     /// ```no_run
277     /// tokio::process::Command::new("sh")
278     ///   .arg("-C")
279     ///   .arg("/path/to/repo");
280     /// ```
281     ///
282     /// To pass multiple arguments see [`args`].
283     ///
284     /// [`args`]: method@Self::args
285     ///
286     /// # Examples
287     ///
288     /// Basic usage:
289     ///
290     /// ```no_run
291     /// use tokio::process::Command;
292     ///
293     /// let command = Command::new("ls")
294     ///         .arg("-l")
295     ///         .arg("-a");
296     /// ```
arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command297     pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
298         self.std.arg(arg);
299         self
300     }
301 
302     /// Adds multiple arguments to pass to the program.
303     ///
304     /// To pass a single argument see [`arg`].
305     ///
306     /// [`arg`]: method@Self::arg
307     ///
308     /// # Examples
309     ///
310     /// Basic usage:
311     ///
312     /// ```no_run
313     /// use tokio::process::Command;
314     ///
315     /// let command = Command::new("ls")
316     ///         .args(&["-l", "-a"]);
317     /// ```
args<I, S>(&mut self, args: I) -> &mut Command where I: IntoIterator<Item = S>, S: AsRef<OsStr>,318     pub fn args<I, S>(&mut self, args: I) -> &mut Command
319     where
320         I: IntoIterator<Item = S>,
321         S: AsRef<OsStr>,
322     {
323         self.std.args(args);
324         self
325     }
326 
327     /// Inserts or updates an environment variable mapping.
328     ///
329     /// Note that environment variable names are case-insensitive (but case-preserving) on Windows,
330     /// and case-sensitive on all other platforms.
331     ///
332     /// # Examples
333     ///
334     /// Basic usage:
335     ///
336     /// ```no_run
337     /// use tokio::process::Command;
338     ///
339     /// let command = Command::new("ls")
340     ///         .env("PATH", "/bin");
341     /// ```
env<K, V>(&mut self, key: K, val: V) -> &mut Command where K: AsRef<OsStr>, V: AsRef<OsStr>,342     pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
343     where
344         K: AsRef<OsStr>,
345         V: AsRef<OsStr>,
346     {
347         self.std.env(key, val);
348         self
349     }
350 
351     /// Adds or updates multiple environment variable mappings.
352     ///
353     /// # Examples
354     ///
355     /// Basic usage:
356     ///
357     /// ```no_run
358     /// use tokio::process::Command;
359     /// use std::process::{Stdio};
360     /// use std::env;
361     /// use std::collections::HashMap;
362     ///
363     /// let filtered_env : HashMap<String, String> =
364     ///     env::vars().filter(|&(ref k, _)|
365     ///         k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
366     ///     ).collect();
367     ///
368     /// let command = Command::new("printenv")
369     ///         .stdin(Stdio::null())
370     ///         .stdout(Stdio::inherit())
371     ///         .env_clear()
372     ///         .envs(&filtered_env);
373     /// ```
envs<I, K, V>(&mut self, vars: I) -> &mut Command where I: IntoIterator<Item = (K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>,374     pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
375     where
376         I: IntoIterator<Item = (K, V)>,
377         K: AsRef<OsStr>,
378         V: AsRef<OsStr>,
379     {
380         self.std.envs(vars);
381         self
382     }
383 
384     /// Removes an environment variable mapping.
385     ///
386     /// # Examples
387     ///
388     /// Basic usage:
389     ///
390     /// ```no_run
391     /// use tokio::process::Command;
392     ///
393     /// let command = Command::new("ls")
394     ///         .env_remove("PATH");
395     /// ```
env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command396     pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
397         self.std.env_remove(key);
398         self
399     }
400 
401     /// Clears the entire environment map for the child process.
402     ///
403     /// # Examples
404     ///
405     /// Basic usage:
406     ///
407     /// ```no_run
408     /// use tokio::process::Command;
409     ///
410     /// let command = Command::new("ls")
411     ///         .env_clear();
412     /// ```
env_clear(&mut self) -> &mut Command413     pub fn env_clear(&mut self) -> &mut Command {
414         self.std.env_clear();
415         self
416     }
417 
418     /// Sets the working directory for the child process.
419     ///
420     /// # Platform-specific behavior
421     ///
422     /// If the program path is relative (e.g., `"./script.sh"`), it's ambiguous
423     /// whether it should be interpreted relative to the parent's working
424     /// directory or relative to `current_dir`. The behavior in this case is
425     /// platform specific and unstable, and it's recommended to use
426     /// [`canonicalize`] to get an absolute program path instead.
427     ///
428     /// [`canonicalize`]: crate::fs::canonicalize()
429     ///
430     /// # Examples
431     ///
432     /// Basic usage:
433     ///
434     /// ```no_run
435     /// use tokio::process::Command;
436     ///
437     /// let command = Command::new("ls")
438     ///         .current_dir("/bin");
439     /// ```
current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command440     pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
441         self.std.current_dir(dir);
442         self
443     }
444 
445     /// Sets configuration for the child process's standard input (stdin) handle.
446     ///
447     /// Defaults to [`inherit`] when used with `spawn` or `status`, and
448     /// defaults to [`piped`] when used with `output`.
449     ///
450     /// [`inherit`]: std::process::Stdio::inherit
451     /// [`piped`]: std::process::Stdio::piped
452     ///
453     /// # Examples
454     ///
455     /// Basic usage:
456     ///
457     /// ```no_run
458     /// use std::process::{Stdio};
459     /// use tokio::process::Command;
460     ///
461     /// let command = Command::new("ls")
462     ///         .stdin(Stdio::null());
463     /// ```
stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command464     pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
465         self.std.stdin(cfg);
466         self
467     }
468 
469     /// Sets configuration for the child process's standard output (stdout) handle.
470     ///
471     /// Defaults to [`inherit`] when used with `spawn` or `status`, and
472     /// defaults to [`piped`] when used with `output`.
473     ///
474     /// [`inherit`]: std::process::Stdio::inherit
475     /// [`piped`]: std::process::Stdio::piped
476     ///
477     /// # Examples
478     ///
479     /// Basic usage:
480     ///
481     /// ```no_run
482     /// use tokio::process::Command;
483     /// use std::process::Stdio;
484     ///
485     /// let command = Command::new("ls")
486     ///         .stdout(Stdio::null());
487     /// ```
stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command488     pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
489         self.std.stdout(cfg);
490         self
491     }
492 
493     /// Sets configuration for the child process's standard error (stderr) handle.
494     ///
495     /// Defaults to [`inherit`] when used with `spawn` or `status`, and
496     /// defaults to [`piped`] when used with `output`.
497     ///
498     /// [`inherit`]: std::process::Stdio::inherit
499     /// [`piped`]: std::process::Stdio::piped
500     ///
501     /// # Examples
502     ///
503     /// Basic usage:
504     ///
505     /// ```no_run
506     /// use tokio::process::Command;
507     /// use std::process::{Stdio};
508     ///
509     /// let command = Command::new("ls")
510     ///         .stderr(Stdio::null());
511     /// ```
stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command512     pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command {
513         self.std.stderr(cfg);
514         self
515     }
516 
517     /// Controls whether a `kill` operation should be invoked on a spawned child
518     /// process when its corresponding `Child` handle is dropped.
519     ///
520     /// By default, this value is assumed to be `false`, meaning the next spawned
521     /// process will not be killed on drop, similar to the behavior of the standard
522     /// library.
523     ///
524     /// # Caveats
525     ///
526     /// On Unix platforms processes must be "reaped" by their parent process after
527     /// they have exited in order to release all OS resources. A child process which
528     /// has exited, but has not yet been reaped by its parent is considered a "zombie"
529     /// process. Such processes continue to count against limits imposed by the system,
530     /// and having too many zombie processes present can prevent additional processes
531     /// from being spawned.
532     ///
533     /// Although issuing a `kill` signal to the child process is a synchronous
534     /// operation, the resulting zombie process cannot be `.await`ed inside of the
535     /// destructor to avoid blocking other tasks. The tokio runtime will, on a
536     /// best-effort basis, attempt to reap and clean up such processes in the
537     /// background, but makes no additional guarantees are made with regards
538     /// how quickly or how often this procedure will take place.
539     ///
540     /// If stronger guarantees are required, it is recommended to avoid dropping
541     /// a [`Child`] handle where possible, and instead utilize `child.wait().await`
542     /// or `child.kill().await` where possible.
kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Command543     pub fn kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Command {
544         self.kill_on_drop = kill_on_drop;
545         self
546     }
547 
548     /// Sets the [process creation flags][1] to be passed to `CreateProcess`.
549     ///
550     /// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`.
551     ///
552     /// [1]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
553     #[cfg(windows)]
creation_flags(&mut self, flags: u32) -> &mut Command554     pub fn creation_flags(&mut self, flags: u32) -> &mut Command {
555         self.std.creation_flags(flags);
556         self
557     }
558 
559     /// Sets the child process's user ID. This translates to a
560     /// `setuid` call in the child process. Failure in the `setuid`
561     /// call will cause the spawn to fail.
562     #[cfg(unix)]
uid(&mut self, id: u32) -> &mut Command563     pub fn uid(&mut self, id: u32) -> &mut Command {
564         self.std.uid(id);
565         self
566     }
567 
568     /// Similar to `uid` but sets the group ID of the child process. This has
569     /// the same semantics as the `uid` field.
570     #[cfg(unix)]
gid(&mut self, id: u32) -> &mut Command571     pub fn gid(&mut self, id: u32) -> &mut Command {
572         self.std.gid(id);
573         self
574     }
575 
576     /// Schedules a closure to be run just before the `exec` function is
577     /// invoked.
578     ///
579     /// The closure is allowed to return an I/O error whose OS error code will
580     /// be communicated back to the parent and returned as an error from when
581     /// the spawn was requested.
582     ///
583     /// Multiple closures can be registered and they will be called in order of
584     /// their registration. If a closure returns `Err` then no further closures
585     /// will be called and the spawn operation will immediately return with a
586     /// failure.
587     ///
588     /// # Safety
589     ///
590     /// This closure will be run in the context of the child process after a
591     /// `fork`. This primarily means that any modifications made to memory on
592     /// behalf of this closure will **not** be visible to the parent process.
593     /// This is often a very constrained environment where normal operations
594     /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
595     /// other threads perhaps still running when the `fork` was run).
596     ///
597     /// This also means that all resources such as file descriptors and
598     /// memory-mapped regions got duplicated. It is your responsibility to make
599     /// sure that the closure does not violate library invariants by making
600     /// invalid use of these duplicates.
601     ///
602     /// When this closure is run, aspects such as the stdio file descriptors and
603     /// working directory have successfully been changed, so output to these
604     /// locations may not appear where intended.
605     #[cfg(unix)]
pre_exec<F>(&mut self, f: F) -> &mut Command where F: FnMut() -> io::Result<()> + Send + Sync + 'static,606     pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Command
607     where
608         F: FnMut() -> io::Result<()> + Send + Sync + 'static,
609     {
610         self.std.pre_exec(f);
611         self
612     }
613 
614     /// Executes the command as a child process, returning a handle to it.
615     ///
616     /// By default, stdin, stdout and stderr are inherited from the parent.
617     ///
618     /// This method will spawn the child process synchronously and return a
619     /// handle to a future-aware child process. The `Child` returned implements
620     /// `Future` itself to acquire the `ExitStatus` of the child, and otherwise
621     /// the `Child` has methods to acquire handles to the stdin, stdout, and
622     /// stderr streams.
623     ///
624     /// All I/O this child does will be associated with the current default
625     /// event loop.
626     ///
627     /// # Examples
628     ///
629     /// Basic usage:
630     ///
631     /// ```no_run
632     /// use tokio::process::Command;
633     ///
634     /// async fn run_ls() -> std::process::ExitStatus {
635     ///     Command::new("ls")
636     ///         .spawn()
637     ///         .expect("ls command failed to start")
638     ///         .wait()
639     ///         .await
640     ///         .expect("ls command failed to run")
641     /// }
642     /// ```
643     ///
644     /// # Caveats
645     ///
646     /// ## Dropping/Cancellation
647     ///
648     /// Similar to the behavior to the standard library, and unlike the futures
649     /// paradigm of dropping-implies-cancellation, a spawned process will, by
650     /// default, continue to execute even after the `Child` handle has been dropped.
651     ///
652     /// The [`Command::kill_on_drop`] method can be used to modify this behavior
653     /// and kill the child process if the `Child` wrapper is dropped before it
654     /// has exited.
655     ///
656     /// ## Unix Processes
657     ///
658     /// On Unix platforms processes must be "reaped" by their parent process after
659     /// they have exited in order to release all OS resources. A child process which
660     /// has exited, but has not yet been reaped by its parent is considered a "zombie"
661     /// process. Such processes continue to count against limits imposed by the system,
662     /// and having too many zombie processes present can prevent additional processes
663     /// from being spawned.
664     ///
665     /// The tokio runtime will, on a best-effort basis, attempt to reap and clean up
666     /// any process which it has spawned. No additional guarantees are made with regards
667     /// how quickly or how often this procedure will take place.
668     ///
669     /// It is recommended to avoid dropping a [`Child`] process handle before it has been
670     /// fully `await`ed if stricter cleanup guarantees are required.
671     ///
672     /// [`Command`]: crate::process::Command
673     /// [`Command::kill_on_drop`]: crate::process::Command::kill_on_drop
674     /// [`Child`]: crate::process::Child
675     ///
676     /// # Errors
677     ///
678     /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
679     /// if the system process limit is reached (which includes other applications
680     /// running on the system).
spawn(&mut self) -> io::Result<Child>681     pub fn spawn(&mut self) -> io::Result<Child> {
682         imp::spawn_child(&mut self.std).map(|spawned_child| Child {
683             child: FusedChild::Child(ChildDropGuard {
684                 inner: spawned_child.child,
685                 kill_on_drop: self.kill_on_drop,
686             }),
687             stdin: spawned_child.stdin.map(|inner| ChildStdin { inner }),
688             stdout: spawned_child.stdout.map(|inner| ChildStdout { inner }),
689             stderr: spawned_child.stderr.map(|inner| ChildStderr { inner }),
690         })
691     }
692 
693     /// Executes the command as a child process, waiting for it to finish and
694     /// collecting its exit status.
695     ///
696     /// By default, stdin, stdout and stderr are inherited from the parent.
697     /// If any input/output handles are set to a pipe then they will be immediately
698     /// closed after the child is spawned.
699     ///
700     /// All I/O this child does will be associated with the current default
701     /// event loop.
702     ///
703     /// The destructor of the future returned by this function will kill
704     /// the child if [`kill_on_drop`] is set to true.
705     ///
706     /// [`kill_on_drop`]: fn@Self::kill_on_drop
707     ///
708     /// # Errors
709     ///
710     /// This future will return an error if the child process cannot be spawned
711     /// or if there is an error while awaiting its status.
712     ///
713     /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
714     /// if the system process limit is reached (which includes other applications
715     /// running on the system).
716     ///
717     /// # Examples
718     ///
719     /// Basic usage:
720     ///
721     /// ```no_run
722     /// use tokio::process::Command;
723     ///
724     /// async fn run_ls() -> std::process::ExitStatus {
725     ///     Command::new("ls")
726     ///         .status()
727     ///         .await
728     ///         .expect("ls command failed to run")
729     /// }
730     /// ```
status(&mut self) -> impl Future<Output = io::Result<ExitStatus>>731     pub fn status(&mut self) -> impl Future<Output = io::Result<ExitStatus>> {
732         let child = self.spawn();
733 
734         async {
735             let mut child = child?;
736 
737             // Ensure we close any stdio handles so we can't deadlock
738             // waiting on the child which may be waiting to read/write
739             // to a pipe we're holding.
740             child.stdin.take();
741             child.stdout.take();
742             child.stderr.take();
743 
744             child.wait().await
745         }
746     }
747 
748     /// Executes the command as a child process, waiting for it to finish and
749     /// collecting all of its output.
750     ///
751     /// > **Note**: this method, unlike the standard library, will
752     /// > unconditionally configure the stdout/stderr handles to be pipes, even
753     /// > if they have been previously configured. If this is not desired then
754     /// > the `spawn` method should be used in combination with the
755     /// > `wait_with_output` method on child.
756     ///
757     /// This method will return a future representing the collection of the
758     /// child process's stdout/stderr. It will resolve to
759     /// the `Output` type in the standard library, containing `stdout` and
760     /// `stderr` as `Vec<u8>` along with an `ExitStatus` representing how the
761     /// process exited.
762     ///
763     /// All I/O this child does will be associated with the current default
764     /// event loop.
765     ///
766     /// The destructor of the future returned by this function will kill
767     /// the child if [`kill_on_drop`] is set to true.
768     ///
769     /// [`kill_on_drop`]: fn@Self::kill_on_drop
770     ///
771     /// # Errors
772     ///
773     /// This future will return an error if the child process cannot be spawned
774     /// or if there is an error while awaiting its status.
775     ///
776     /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
777     /// if the system process limit is reached (which includes other applications
778     /// running on the system).
779     /// # Examples
780     ///
781     /// Basic usage:
782     ///
783     /// ```no_run
784     /// use tokio::process::Command;
785     ///
786     /// async fn run_ls() {
787     ///     let output: std::process::Output = Command::new("ls")
788     ///         .output()
789     ///         .await
790     ///         .expect("ls command failed to run");
791     ///     println!("stderr of ls: {:?}", output.stderr);
792     /// }
793     /// ```
output(&mut self) -> impl Future<Output = io::Result<Output>>794     pub fn output(&mut self) -> impl Future<Output = io::Result<Output>> {
795         self.std.stdout(Stdio::piped());
796         self.std.stderr(Stdio::piped());
797 
798         let child = self.spawn();
799 
800         async { child?.wait_with_output().await }
801     }
802 }
803 
804 impl From<StdCommand> for Command {
from(std: StdCommand) -> Command805     fn from(std: StdCommand) -> Command {
806         Command {
807             std,
808             kill_on_drop: false,
809         }
810     }
811 }
812 
813 /// A drop guard which can ensure the child process is killed on drop if specified.
814 #[derive(Debug)]
815 struct ChildDropGuard<T: Kill> {
816     inner: T,
817     kill_on_drop: bool,
818 }
819 
820 impl<T: Kill> Kill for ChildDropGuard<T> {
kill(&mut self) -> io::Result<()>821     fn kill(&mut self) -> io::Result<()> {
822         let ret = self.inner.kill();
823 
824         if ret.is_ok() {
825             self.kill_on_drop = false;
826         }
827 
828         ret
829     }
830 }
831 
832 impl<T: Kill> Drop for ChildDropGuard<T> {
drop(&mut self)833     fn drop(&mut self) {
834         if self.kill_on_drop {
835             drop(self.kill());
836         }
837     }
838 }
839 
840 impl<T, E, F> Future for ChildDropGuard<F>
841 where
842     F: Future<Output = Result<T, E>> + Kill + Unpin,
843 {
844     type Output = Result<T, E>;
845 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>846     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
847         // Keep track of task budget
848         let coop = ready!(crate::coop::poll_proceed(cx));
849 
850         let ret = Pin::new(&mut self.inner).poll(cx);
851 
852         if let Poll::Ready(Ok(_)) = ret {
853             // Avoid the overhead of trying to kill a reaped process
854             self.kill_on_drop = false;
855         }
856 
857         if ret.is_ready() {
858             coop.made_progress();
859         }
860 
861         ret
862     }
863 }
864 
865 /// Keeps track of the exit status of a child process without worrying about
866 /// polling the underlying futures even after they have completed.
867 #[derive(Debug)]
868 enum FusedChild {
869     Child(ChildDropGuard<imp::Child>),
870     Done(ExitStatus),
871 }
872 
873 /// Representation of a child process spawned onto an event loop.
874 ///
875 /// # Caveats
876 /// Similar to the behavior to the standard library, and unlike the futures
877 /// paradigm of dropping-implies-cancellation, a spawned process will, by
878 /// default, continue to execute even after the `Child` handle has been dropped.
879 ///
880 /// The `Command::kill_on_drop` method can be used to modify this behavior
881 /// and kill the child process if the `Child` wrapper is dropped before it
882 /// has exited.
883 #[derive(Debug)]
884 pub struct Child {
885     child: FusedChild,
886 
887     /// The handle for writing to the child's standard input (stdin), if it has
888     /// been captured. To avoid partially moving the `child` and thus blocking
889     /// yourself from calling functions on `child` while using `stdin`, you might
890     /// find it helpful to do:
891     ///
892     /// ```no_run
893     /// # let mut child = tokio::process::Command::new("echo").spawn().unwrap();
894     /// let stdin = child.stdin.take().unwrap();
895     /// ```
896     pub stdin: Option<ChildStdin>,
897 
898     /// The handle for reading from the child's standard output (stdout), if it
899     /// has been captured. You might find it helpful to do
900     ///
901     /// ```no_run
902     /// # let mut child = tokio::process::Command::new("echo").spawn().unwrap();
903     /// let stdout = child.stdout.take().unwrap();
904     /// ```
905     ///
906     /// to avoid partially moving the `child` and thus blocking yourself from calling
907     /// functions on `child` while using `stdout`.
908     pub stdout: Option<ChildStdout>,
909 
910     /// The handle for reading from the child's standard error (stderr), if it
911     /// has been captured. You might find it helpful to do
912     ///
913     /// ```no_run
914     /// # let mut child = tokio::process::Command::new("echo").spawn().unwrap();
915     /// let stderr = child.stderr.take().unwrap();
916     /// ```
917     ///
918     /// to avoid partially moving the `child` and thus blocking yourself from calling
919     /// functions on `child` while using `stderr`.
920     pub stderr: Option<ChildStderr>,
921 }
922 
923 impl Child {
924     /// Returns the OS-assigned process identifier associated with this child
925     /// while it is still running.
926     ///
927     /// Once the child has been polled to completion this will return `None`.
928     /// This is done to avoid confusion on platforms like Unix where the OS
929     /// identifier could be reused once the process has completed.
id(&self) -> Option<u32>930     pub fn id(&self) -> Option<u32> {
931         match &self.child {
932             FusedChild::Child(child) => Some(child.inner.id()),
933             FusedChild::Done(_) => None,
934         }
935     }
936 
937     /// Attempts to force the child to exit, but does not wait for the request
938     /// to take effect.
939     ///
940     /// On Unix platforms, this is the equivalent to sending a SIGKILL. Note
941     /// that on Unix platforms it is possible for a zombie process to remain
942     /// after a kill is sent; to avoid this, the caller should ensure that either
943     /// `child.wait().await` or `child.try_wait()` is invoked successfully.
start_kill(&mut self) -> io::Result<()>944     pub fn start_kill(&mut self) -> io::Result<()> {
945         match &mut self.child {
946             FusedChild::Child(child) => child.kill(),
947             FusedChild::Done(_) => Err(io::Error::new(
948                 io::ErrorKind::InvalidInput,
949                 "invalid argument: can't kill an exited process",
950             )),
951         }
952     }
953 
954     /// Forces the child to exit.
955     ///
956     /// This is equivalent to sending a SIGKILL on unix platforms.
957     ///
958     /// If the child has to be killed remotely, it is possible to do it using
959     /// a combination of the select! macro and a oneshot channel. In the following
960     /// example, the child will run until completion unless a message is sent on
961     /// the oneshot channel. If that happens, the child is killed immediately
962     /// using the `.kill()` method.
963     ///
964     /// ```no_run
965     /// use tokio::process::Command;
966     /// use tokio::sync::oneshot::channel;
967     ///
968     /// #[tokio::main]
969     /// async fn main() {
970     ///     let (send, recv) = channel::<()>();
971     ///     let mut child = Command::new("sleep").arg("1").spawn().unwrap();
972     ///     tokio::spawn(async move { send.send(()) });
973     ///     tokio::select! {
974     ///         _ = child.wait() => {}
975     ///         _ = recv => child.kill().await.expect("kill failed"),
976     ///     }
977     /// }
978     /// ```
kill(&mut self) -> io::Result<()>979     pub async fn kill(&mut self) -> io::Result<()> {
980         self.start_kill()?;
981         self.wait().await?;
982         Ok(())
983     }
984 
985     /// Waits for the child to exit completely, returning the status that it
986     /// exited with. This function will continue to have the same return value
987     /// after it has been called at least once.
988     ///
989     /// The stdin handle to the child process, if any, will be closed
990     /// before waiting. This helps avoid deadlock: it ensures that the
991     /// child does not block waiting for input from the parent, while
992     /// the parent waits for the child to exit.
993     ///
994     /// If the caller wishes to explicitly control when the child's stdin
995     /// handle is closed, they may `.take()` it before calling `.wait()`:
996     ///
997     /// ```no_run
998     /// use tokio::io::AsyncWriteExt;
999     /// use tokio::process::Command;
1000     ///
1001     /// #[tokio::main]
1002     /// async fn main() {
1003     ///     let mut child = Command::new("cat").spawn().unwrap();
1004     ///
1005     ///     let mut stdin = child.stdin.take().unwrap();
1006     ///     tokio::spawn(async move {
1007     ///         // do something with stdin here...
1008     ///         stdin.write_all(b"hello world\n").await.unwrap();
1009     ///
1010     ///         // then drop when finished
1011     ///         drop(stdin);
1012     ///     });
1013     ///
1014     ///     // wait for the process to complete
1015     ///     let _ = child.wait().await;
1016     /// }
1017     /// ```
wait(&mut self) -> io::Result<ExitStatus>1018     pub async fn wait(&mut self) -> io::Result<ExitStatus> {
1019         // Ensure stdin is closed so the child isn't stuck waiting on
1020         // input while the parent is waiting for it to exit.
1021         drop(self.stdin.take());
1022 
1023         match &mut self.child {
1024             FusedChild::Done(exit) => Ok(*exit),
1025             FusedChild::Child(child) => {
1026                 let ret = child.await;
1027 
1028                 if let Ok(exit) = ret {
1029                     self.child = FusedChild::Done(exit);
1030                 }
1031 
1032                 ret
1033             }
1034         }
1035     }
1036 
1037     /// Attempts to collect the exit status of the child if it has already
1038     /// exited.
1039     ///
1040     /// This function will not block the calling thread and will only
1041     /// check to see if the child process has exited or not. If the child has
1042     /// exited then on Unix the process ID is reaped. This function is
1043     /// guaranteed to repeatedly return a successful exit status so long as the
1044     /// child has already exited.
1045     ///
1046     /// If the child has exited, then `Ok(Some(status))` is returned. If the
1047     /// exit status is not available at this time then `Ok(None)` is returned.
1048     /// If an error occurs, then that error is returned.
1049     ///
1050     /// Note that unlike `wait`, this function will not attempt to drop stdin,
1051     /// nor will it wake the current task if the child exits.
try_wait(&mut self) -> io::Result<Option<ExitStatus>>1052     pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
1053         match &mut self.child {
1054             FusedChild::Done(exit) => Ok(Some(*exit)),
1055             FusedChild::Child(guard) => {
1056                 let ret = guard.inner.try_wait();
1057 
1058                 if let Ok(Some(exit)) = ret {
1059                     // Avoid the overhead of trying to kill a reaped process
1060                     guard.kill_on_drop = false;
1061                     self.child = FusedChild::Done(exit);
1062                 }
1063 
1064                 ret
1065             }
1066         }
1067     }
1068 
1069     /// Returns a future that will resolve to an `Output`, containing the exit
1070     /// status, stdout, and stderr of the child process.
1071     ///
1072     /// The returned future will simultaneously waits for the child to exit and
1073     /// collect all remaining output on the stdout/stderr handles, returning an
1074     /// `Output` instance.
1075     ///
1076     /// The stdin handle to the child process, if any, will be closed before
1077     /// waiting. This helps avoid deadlock: it ensures that the child does not
1078     /// block waiting for input from the parent, while the parent waits for the
1079     /// child to exit.
1080     ///
1081     /// By default, stdin, stdout and stderr are inherited from the parent. In
1082     /// order to capture the output into this `Output` it is necessary to create
1083     /// new pipes between parent and child. Use `stdout(Stdio::piped())` or
1084     /// `stderr(Stdio::piped())`, respectively, when creating a `Command`.
wait_with_output(mut self) -> io::Result<Output>1085     pub async fn wait_with_output(mut self) -> io::Result<Output> {
1086         use crate::future::try_join3;
1087 
1088         async fn read_to_end<A: AsyncRead + Unpin>(io: Option<A>) -> io::Result<Vec<u8>> {
1089             let mut vec = Vec::new();
1090             if let Some(mut io) = io {
1091                 crate::io::util::read_to_end(&mut io, &mut vec).await?;
1092             }
1093             Ok(vec)
1094         }
1095 
1096         let stdout_fut = read_to_end(self.stdout.take());
1097         let stderr_fut = read_to_end(self.stderr.take());
1098 
1099         let (status, stdout, stderr) = try_join3(self.wait(), stdout_fut, stderr_fut).await?;
1100 
1101         Ok(Output {
1102             status,
1103             stdout,
1104             stderr,
1105         })
1106     }
1107 }
1108 
1109 /// The standard input stream for spawned children.
1110 ///
1111 /// This type implements the `AsyncWrite` trait to pass data to the stdin handle of
1112 /// handle of a child process asynchronously.
1113 #[derive(Debug)]
1114 pub struct ChildStdin {
1115     inner: imp::ChildStdin,
1116 }
1117 
1118 /// The standard output stream for spawned children.
1119 ///
1120 /// This type implements the `AsyncRead` trait to read data from the stdout
1121 /// handle of a child process asynchronously.
1122 #[derive(Debug)]
1123 pub struct ChildStdout {
1124     inner: imp::ChildStdout,
1125 }
1126 
1127 /// The standard error stream for spawned children.
1128 ///
1129 /// This type implements the `AsyncRead` trait to read data from the stderr
1130 /// handle of a child process asynchronously.
1131 #[derive(Debug)]
1132 pub struct ChildStderr {
1133     inner: imp::ChildStderr,
1134 }
1135 
1136 impl AsyncWrite for ChildStdin {
poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<io::Result<usize>>1137     fn poll_write(
1138         self: Pin<&mut Self>,
1139         cx: &mut Context<'_>,
1140         buf: &[u8],
1141     ) -> Poll<io::Result<usize>> {
1142         self.inner.poll_write(cx, buf)
1143     }
1144 
poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>>1145     fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
1146         Poll::Ready(Ok(()))
1147     }
1148 
poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>>1149     fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
1150         Poll::Ready(Ok(()))
1151     }
1152 }
1153 
1154 impl AsyncRead for ChildStdout {
poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<io::Result<()>>1155     fn poll_read(
1156         self: Pin<&mut Self>,
1157         cx: &mut Context<'_>,
1158         buf: &mut ReadBuf<'_>,
1159     ) -> Poll<io::Result<()>> {
1160         // Safety: pipes support reading into uninitialized memory
1161         unsafe { self.inner.poll_read(cx, buf) }
1162     }
1163 }
1164 
1165 impl AsyncRead for ChildStderr {
poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<io::Result<()>>1166     fn poll_read(
1167         self: Pin<&mut Self>,
1168         cx: &mut Context<'_>,
1169         buf: &mut ReadBuf<'_>,
1170     ) -> Poll<io::Result<()>> {
1171         // Safety: pipes support reading into uninitialized memory
1172         unsafe { self.inner.poll_read(cx, buf) }
1173     }
1174 }
1175 
1176 impl TryInto<Stdio> for ChildStdin {
1177     type Error = io::Error;
1178 
try_into(self) -> Result<Stdio, Self::Error>1179     fn try_into(self) -> Result<Stdio, Self::Error> {
1180         imp::convert_to_stdio(self.inner)
1181     }
1182 }
1183 
1184 impl TryInto<Stdio> for ChildStdout {
1185     type Error = io::Error;
1186 
try_into(self) -> Result<Stdio, Self::Error>1187     fn try_into(self) -> Result<Stdio, Self::Error> {
1188         imp::convert_to_stdio(self.inner)
1189     }
1190 }
1191 
1192 impl TryInto<Stdio> for ChildStderr {
1193     type Error = io::Error;
1194 
try_into(self) -> Result<Stdio, Self::Error>1195     fn try_into(self) -> Result<Stdio, Self::Error> {
1196         imp::convert_to_stdio(self.inner)
1197     }
1198 }
1199 
1200 #[cfg(unix)]
1201 mod sys {
1202     use std::os::unix::io::{AsRawFd, RawFd};
1203 
1204     use super::{ChildStderr, ChildStdin, ChildStdout};
1205 
1206     impl AsRawFd for ChildStdin {
as_raw_fd(&self) -> RawFd1207         fn as_raw_fd(&self) -> RawFd {
1208             self.inner.as_raw_fd()
1209         }
1210     }
1211 
1212     impl AsRawFd for ChildStdout {
as_raw_fd(&self) -> RawFd1213         fn as_raw_fd(&self) -> RawFd {
1214             self.inner.as_raw_fd()
1215         }
1216     }
1217 
1218     impl AsRawFd for ChildStderr {
as_raw_fd(&self) -> RawFd1219         fn as_raw_fd(&self) -> RawFd {
1220             self.inner.as_raw_fd()
1221         }
1222     }
1223 }
1224 
1225 #[cfg(windows)]
1226 mod sys {
1227     use std::os::windows::io::{AsRawHandle, RawHandle};
1228 
1229     use super::{ChildStderr, ChildStdin, ChildStdout};
1230 
1231     impl AsRawHandle for ChildStdin {
as_raw_handle(&self) -> RawHandle1232         fn as_raw_handle(&self) -> RawHandle {
1233             self.inner.as_raw_handle()
1234         }
1235     }
1236 
1237     impl AsRawHandle for ChildStdout {
as_raw_handle(&self) -> RawHandle1238         fn as_raw_handle(&self) -> RawHandle {
1239             self.inner.as_raw_handle()
1240         }
1241     }
1242 
1243     impl AsRawHandle for ChildStderr {
as_raw_handle(&self) -> RawHandle1244         fn as_raw_handle(&self) -> RawHandle {
1245             self.inner.as_raw_handle()
1246         }
1247     }
1248 }
1249 
1250 #[cfg(all(test, not(loom)))]
1251 mod test {
1252     use super::kill::Kill;
1253     use super::ChildDropGuard;
1254 
1255     use futures::future::FutureExt;
1256     use std::future::Future;
1257     use std::io;
1258     use std::pin::Pin;
1259     use std::task::{Context, Poll};
1260 
1261     struct Mock {
1262         num_kills: usize,
1263         num_polls: usize,
1264         poll_result: Poll<Result<(), ()>>,
1265     }
1266 
1267     impl Mock {
new() -> Self1268         fn new() -> Self {
1269             Self::with_result(Poll::Pending)
1270         }
1271 
with_result(result: Poll<Result<(), ()>>) -> Self1272         fn with_result(result: Poll<Result<(), ()>>) -> Self {
1273             Self {
1274                 num_kills: 0,
1275                 num_polls: 0,
1276                 poll_result: result,
1277             }
1278         }
1279     }
1280 
1281     impl Kill for Mock {
kill(&mut self) -> io::Result<()>1282         fn kill(&mut self) -> io::Result<()> {
1283             self.num_kills += 1;
1284             Ok(())
1285         }
1286     }
1287 
1288     impl Future for Mock {
1289         type Output = Result<(), ()>;
1290 
poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output>1291         fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
1292             let inner = Pin::get_mut(self);
1293             inner.num_polls += 1;
1294             inner.poll_result
1295         }
1296     }
1297 
1298     #[test]
kills_on_drop_if_specified()1299     fn kills_on_drop_if_specified() {
1300         let mut mock = Mock::new();
1301 
1302         {
1303             let guard = ChildDropGuard {
1304                 inner: &mut mock,
1305                 kill_on_drop: true,
1306             };
1307             drop(guard);
1308         }
1309 
1310         assert_eq!(1, mock.num_kills);
1311         assert_eq!(0, mock.num_polls);
1312     }
1313 
1314     #[test]
no_kill_on_drop_by_default()1315     fn no_kill_on_drop_by_default() {
1316         let mut mock = Mock::new();
1317 
1318         {
1319             let guard = ChildDropGuard {
1320                 inner: &mut mock,
1321                 kill_on_drop: false,
1322             };
1323             drop(guard);
1324         }
1325 
1326         assert_eq!(0, mock.num_kills);
1327         assert_eq!(0, mock.num_polls);
1328     }
1329 
1330     #[test]
no_kill_if_already_killed()1331     fn no_kill_if_already_killed() {
1332         let mut mock = Mock::new();
1333 
1334         {
1335             let mut guard = ChildDropGuard {
1336                 inner: &mut mock,
1337                 kill_on_drop: true,
1338             };
1339             let _ = guard.kill();
1340             drop(guard);
1341         }
1342 
1343         assert_eq!(1, mock.num_kills);
1344         assert_eq!(0, mock.num_polls);
1345     }
1346 
1347     #[test]
no_kill_if_reaped()1348     fn no_kill_if_reaped() {
1349         let mut mock_pending = Mock::with_result(Poll::Pending);
1350         let mut mock_reaped = Mock::with_result(Poll::Ready(Ok(())));
1351         let mut mock_err = Mock::with_result(Poll::Ready(Err(())));
1352 
1353         let waker = futures::task::noop_waker();
1354         let mut context = Context::from_waker(&waker);
1355         {
1356             let mut guard = ChildDropGuard {
1357                 inner: &mut mock_pending,
1358                 kill_on_drop: true,
1359             };
1360             let _ = guard.poll_unpin(&mut context);
1361 
1362             let mut guard = ChildDropGuard {
1363                 inner: &mut mock_reaped,
1364                 kill_on_drop: true,
1365             };
1366             let _ = guard.poll_unpin(&mut context);
1367 
1368             let mut guard = ChildDropGuard {
1369                 inner: &mut mock_err,
1370                 kill_on_drop: true,
1371             };
1372             let _ = guard.poll_unpin(&mut context);
1373         }
1374 
1375         assert_eq!(1, mock_pending.num_kills);
1376         assert_eq!(1, mock_pending.num_polls);
1377 
1378         assert_eq!(0, mock_reaped.num_kills);
1379         assert_eq!(1, mock_reaped.num_polls);
1380 
1381         assert_eq!(1, mock_err.num_kills);
1382         assert_eq!(1, mock_err.num_polls);
1383     }
1384 }
1385