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 behaviour 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}
1679