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