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