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)] 113 mod imp; 114 115 #[path = "windows.rs"] 116 #[cfg(windows)] 117 mod imp; 118 119 mod kill; 120 121 use crate::io::{AsyncRead, AsyncWrite}; 122 use crate::process::kill::Kill; 123 124 use std::ffi::OsStr; 125 use std::future::Future; 126 use std::io; 127 #[cfg(unix)] 128 use std::os::unix::process::CommandExt; 129 #[cfg(windows)] 130 use std::os::windows::process::CommandExt; 131 use std::path::Path; 132 use std::pin::Pin; 133 use std::process::{Command as StdCommand, ExitStatus, Output, Stdio}; 134 use std::task::Context; 135 use 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)] 144 pub struct Command { 145 std: StdCommand, 146 kill_on_drop: bool, 147 } 148 149 pub(crate) struct SpawnedChild { 150 child: imp::Child, 151 stdin: Option<imp::ChildStdin>, 152 stdout: Option<imp::ChildStdout>, 153 stderr: Option<imp::ChildStderr>, 154 } 155 156 impl 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 /// ``` new<S: AsRef<OsStr>>(program: S) -> Command184 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 /// ``` arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command220 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 /// ``` args<I, S>(&mut self, args: I) -> &mut Command where I: IntoIterator<Item = S>, S: AsRef<OsStr>,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 /// ``` env<K, V>(&mut self, key: K, val: V) -> &mut Command where K: AsRef<OsStr>, V: AsRef<OsStr>,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 /// ``` envs<I, K, V>(&mut self, vars: I) -> &mut Command where I: IntoIterator<Item = (K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>,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 /// ``` env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command319 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 /// ``` env_clear(&mut self) -> &mut Command336 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 /// ``` current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command363 pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command { 364 self.std.current_dir(dir); 365 self 366 } 367 368 /// Sets 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 /// ``` stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command387 pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command { 388 self.std.stdin(cfg); 389 self 390 } 391 392 /// Sets 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 /// ``` stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command411 pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command { 412 self.std.stdout(cfg); 413 self 414 } 415 416 /// Sets 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 /// ``` stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command435 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. kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Command446 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)] creation_flags(&mut self, flags: u32) -> &mut Command457 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)] uid(&mut self, id: u32) -> &mut Command466 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)] gid(&mut self, id: u32) -> &mut Command474 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)] pre_exec<F>(&mut self, f: F) -> &mut Command where F: FnMut() -> io::Result<()> + Send + Sync + 'static,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 /// ``` spawn(&mut self) -> io::Result<Child>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 the 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 /// } status(&mut self) -> impl Future<Output = io::Result<ExitStatus>>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 /// } output(&mut self) -> impl Future<Output = io::Result<Output>>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 660 impl From<StdCommand> for Command { from(std: StdCommand) -> Command661 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)] 671 struct ChildDropGuard<T: Kill> { 672 inner: T, 673 kill_on_drop: bool, 674 } 675 676 impl<T: Kill> Kill for ChildDropGuard<T> { kill(&mut self) -> io::Result<()>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 688 impl<T: Kill> Drop for ChildDropGuard<T> { drop(&mut self)689 fn drop(&mut self) { 690 if self.kill_on_drop { 691 drop(self.kill()); 692 } 693 } 694 } 695 696 impl<T, E, F> Future for ChildDropGuard<F> 697 where 698 F: Future<Output = Result<T, E>> + Kill + Unpin, 699 { 700 type Output = Result<T, E>; 701 poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>702 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 703 // Keep track of task budget 704 ready!(crate::coop::poll_proceed(cx)); 705 706 let ret = Pin::new(&mut self.inner).poll(cx); 707 708 if let Poll::Ready(Ok(_)) = ret { 709 // Avoid the overhead of trying to kill a reaped process 710 self.kill_on_drop = false; 711 } 712 713 ret 714 } 715 } 716 717 /// Representation of a child process spawned onto an event loop. 718 /// 719 /// This type is also a future which will yield the `ExitStatus` of the 720 /// underlying child process. A `Child` here also provides access to information 721 /// like the OS-assigned identifier and the stdio streams. 722 /// 723 /// # Caveats 724 /// Similar to the behavior to the standard library, and unlike the futures 725 /// paradigm of dropping-implies-cancellation, a spawned process will, by 726 /// default, continue to execute even after the `Child` handle has been dropped. 727 /// 728 /// The `Command::kill_on_drop` method can be used to modify this behavior 729 /// and kill the child process if the `Child` wrapper is dropped before it 730 /// has exited. 731 #[must_use = "futures do nothing unless polled"] 732 #[derive(Debug)] 733 pub struct Child { 734 child: ChildDropGuard<imp::Child>, 735 736 /// The handle for writing to the child's standard input (stdin), if it has 737 /// been captured. 738 pub stdin: Option<ChildStdin>, 739 740 /// The handle for reading from the child's standard output (stdout), if it 741 /// has been captured. 742 pub stdout: Option<ChildStdout>, 743 744 /// The handle for reading from the child's standard error (stderr), if it 745 /// has been captured. 746 pub stderr: Option<ChildStderr>, 747 } 748 749 impl Child { 750 /// Returns the OS-assigned process identifier associated with this child. id(&self) -> u32751 pub fn id(&self) -> u32 { 752 self.child.inner.id() 753 } 754 755 /// Forces the child to exit. 756 /// 757 /// This is equivalent to sending a SIGKILL on unix platforms. kill(&mut self) -> io::Result<()>758 pub fn kill(&mut self) -> io::Result<()> { 759 self.child.kill() 760 } 761 762 #[doc(hidden)] 763 #[deprecated(note = "please use `child.stdin` instead")] stdin(&mut self) -> &mut Option<ChildStdin>764 pub fn stdin(&mut self) -> &mut Option<ChildStdin> { 765 &mut self.stdin 766 } 767 768 #[doc(hidden)] 769 #[deprecated(note = "please use `child.stdout` instead")] stdout(&mut self) -> &mut Option<ChildStdout>770 pub fn stdout(&mut self) -> &mut Option<ChildStdout> { 771 &mut self.stdout 772 } 773 774 #[doc(hidden)] 775 #[deprecated(note = "please use `child.stderr` instead")] stderr(&mut self) -> &mut Option<ChildStderr>776 pub fn stderr(&mut self) -> &mut Option<ChildStderr> { 777 &mut self.stderr 778 } 779 780 /// Returns a future that will resolve to an `Output`, containing the exit 781 /// status, stdout, and stderr of the child process. 782 /// 783 /// The returned future will simultaneously waits for the child to exit and 784 /// collect all remaining output on the stdout/stderr handles, returning an 785 /// `Output` instance. 786 /// 787 /// The stdin handle to the child process, if any, will be closed before 788 /// waiting. This helps avoid deadlock: it ensures that the child does not 789 /// block waiting for input from the parent, while the parent waits for the 790 /// child to exit. 791 /// 792 /// By default, stdin, stdout and stderr are inherited from the parent. In 793 /// order to capture the output into this `Output` it is necessary to create 794 /// new pipes between parent and child. Use `stdout(Stdio::piped())` or 795 /// `stderr(Stdio::piped())`, respectively, when creating a `Command`. wait_with_output(mut self) -> io::Result<Output>796 pub async fn wait_with_output(mut self) -> io::Result<Output> { 797 use crate::future::try_join3; 798 799 async fn read_to_end<A: AsyncRead + Unpin>(io: Option<A>) -> io::Result<Vec<u8>> { 800 let mut vec = Vec::new(); 801 if let Some(mut io) = io { 802 crate::io::util::read_to_end(&mut io, &mut vec).await?; 803 } 804 Ok(vec) 805 } 806 807 drop(self.stdin.take()); 808 let stdout_fut = read_to_end(self.stdout.take()); 809 let stderr_fut = read_to_end(self.stderr.take()); 810 811 let (status, stdout, stderr) = try_join3(self, stdout_fut, stderr_fut).await?; 812 813 Ok(Output { 814 status, 815 stdout, 816 stderr, 817 }) 818 } 819 } 820 821 impl Future for Child { 822 type Output = io::Result<ExitStatus>; 823 poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>824 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 825 Pin::new(&mut self.child).poll(cx) 826 } 827 } 828 829 /// The standard input stream for spawned children. 830 /// 831 /// This type implements the `AsyncWrite` trait to pass data to the stdin handle of 832 /// handle of a child process asynchronously. 833 #[derive(Debug)] 834 pub struct ChildStdin { 835 inner: imp::ChildStdin, 836 } 837 838 /// The standard output stream for spawned children. 839 /// 840 /// This type implements the `AsyncRead` trait to read data from the stdout 841 /// handle of a child process asynchronously. 842 #[derive(Debug)] 843 pub struct ChildStdout { 844 inner: imp::ChildStdout, 845 } 846 847 /// The standard error stream for spawned children. 848 /// 849 /// This type implements the `AsyncRead` trait to read data from the stderr 850 /// handle of a child process asynchronously. 851 #[derive(Debug)] 852 pub struct ChildStderr { 853 inner: imp::ChildStderr, 854 } 855 856 impl AsyncWrite for ChildStdin { poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<io::Result<usize>>857 fn poll_write( 858 mut self: Pin<&mut Self>, 859 cx: &mut Context<'_>, 860 buf: &[u8], 861 ) -> Poll<io::Result<usize>> { 862 Pin::new(&mut self.inner).poll_write(cx, buf) 863 } 864 poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>865 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { 866 Pin::new(&mut self.inner).poll_flush(cx) 867 } 868 poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>>869 fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { 870 Pin::new(&mut self.inner).poll_shutdown(cx) 871 } 872 } 873 874 impl AsyncRead for ChildStdout { poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<io::Result<usize>>875 fn poll_read( 876 mut self: Pin<&mut Self>, 877 cx: &mut Context<'_>, 878 buf: &mut [u8], 879 ) -> Poll<io::Result<usize>> { 880 Pin::new(&mut self.inner).poll_read(cx, buf) 881 } 882 } 883 884 impl AsyncRead for ChildStderr { poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll<io::Result<usize>>885 fn poll_read( 886 mut self: Pin<&mut Self>, 887 cx: &mut Context<'_>, 888 buf: &mut [u8], 889 ) -> Poll<io::Result<usize>> { 890 Pin::new(&mut self.inner).poll_read(cx, buf) 891 } 892 } 893 894 #[cfg(unix)] 895 mod sys { 896 use std::os::unix::io::{AsRawFd, RawFd}; 897 898 use super::{ChildStderr, ChildStdin, ChildStdout}; 899 900 impl AsRawFd for ChildStdin { as_raw_fd(&self) -> RawFd901 fn as_raw_fd(&self) -> RawFd { 902 self.inner.get_ref().as_raw_fd() 903 } 904 } 905 906 impl AsRawFd for ChildStdout { as_raw_fd(&self) -> RawFd907 fn as_raw_fd(&self) -> RawFd { 908 self.inner.get_ref().as_raw_fd() 909 } 910 } 911 912 impl AsRawFd for ChildStderr { as_raw_fd(&self) -> RawFd913 fn as_raw_fd(&self) -> RawFd { 914 self.inner.get_ref().as_raw_fd() 915 } 916 } 917 } 918 919 #[cfg(windows)] 920 mod sys { 921 use std::os::windows::io::{AsRawHandle, RawHandle}; 922 923 use super::{ChildStderr, ChildStdin, ChildStdout}; 924 925 impl AsRawHandle for ChildStdin { as_raw_handle(&self) -> RawHandle926 fn as_raw_handle(&self) -> RawHandle { 927 self.inner.get_ref().as_raw_handle() 928 } 929 } 930 931 impl AsRawHandle for ChildStdout { as_raw_handle(&self) -> RawHandle932 fn as_raw_handle(&self) -> RawHandle { 933 self.inner.get_ref().as_raw_handle() 934 } 935 } 936 937 impl AsRawHandle for ChildStderr { as_raw_handle(&self) -> RawHandle938 fn as_raw_handle(&self) -> RawHandle { 939 self.inner.get_ref().as_raw_handle() 940 } 941 } 942 } 943 944 #[cfg(all(test, not(loom)))] 945 mod test { 946 use super::kill::Kill; 947 use super::ChildDropGuard; 948 949 use futures::future::FutureExt; 950 use std::future::Future; 951 use std::io; 952 use std::pin::Pin; 953 use std::task::{Context, Poll}; 954 955 struct Mock { 956 num_kills: usize, 957 num_polls: usize, 958 poll_result: Poll<Result<(), ()>>, 959 } 960 961 impl Mock { new() -> Self962 fn new() -> Self { 963 Self::with_result(Poll::Pending) 964 } 965 with_result(result: Poll<Result<(), ()>>) -> Self966 fn with_result(result: Poll<Result<(), ()>>) -> Self { 967 Self { 968 num_kills: 0, 969 num_polls: 0, 970 poll_result: result, 971 } 972 } 973 } 974 975 impl Kill for Mock { kill(&mut self) -> io::Result<()>976 fn kill(&mut self) -> io::Result<()> { 977 self.num_kills += 1; 978 Ok(()) 979 } 980 } 981 982 impl Future for Mock { 983 type Output = Result<(), ()>; 984 poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output>985 fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> { 986 let inner = Pin::get_mut(self); 987 inner.num_polls += 1; 988 inner.poll_result 989 } 990 } 991 992 #[test] kills_on_drop_if_specified()993 fn kills_on_drop_if_specified() { 994 let mut mock = Mock::new(); 995 996 { 997 let guard = ChildDropGuard { 998 inner: &mut mock, 999 kill_on_drop: true, 1000 }; 1001 drop(guard); 1002 } 1003 1004 assert_eq!(1, mock.num_kills); 1005 assert_eq!(0, mock.num_polls); 1006 } 1007 1008 #[test] no_kill_on_drop_by_default()1009 fn no_kill_on_drop_by_default() { 1010 let mut mock = Mock::new(); 1011 1012 { 1013 let guard = ChildDropGuard { 1014 inner: &mut mock, 1015 kill_on_drop: false, 1016 }; 1017 drop(guard); 1018 } 1019 1020 assert_eq!(0, mock.num_kills); 1021 assert_eq!(0, mock.num_polls); 1022 } 1023 1024 #[test] no_kill_if_already_killed()1025 fn no_kill_if_already_killed() { 1026 let mut mock = Mock::new(); 1027 1028 { 1029 let mut guard = ChildDropGuard { 1030 inner: &mut mock, 1031 kill_on_drop: true, 1032 }; 1033 let _ = guard.kill(); 1034 drop(guard); 1035 } 1036 1037 assert_eq!(1, mock.num_kills); 1038 assert_eq!(0, mock.num_polls); 1039 } 1040 1041 #[test] no_kill_if_reaped()1042 fn no_kill_if_reaped() { 1043 let mut mock_pending = Mock::with_result(Poll::Pending); 1044 let mut mock_reaped = Mock::with_result(Poll::Ready(Ok(()))); 1045 let mut mock_err = Mock::with_result(Poll::Ready(Err(()))); 1046 1047 let waker = futures::task::noop_waker(); 1048 let mut context = Context::from_waker(&waker); 1049 { 1050 let mut guard = ChildDropGuard { 1051 inner: &mut mock_pending, 1052 kill_on_drop: true, 1053 }; 1054 let _ = guard.poll_unpin(&mut context); 1055 1056 let mut guard = ChildDropGuard { 1057 inner: &mut mock_reaped, 1058 kill_on_drop: true, 1059 }; 1060 let _ = guard.poll_unpin(&mut context); 1061 1062 let mut guard = ChildDropGuard { 1063 inner: &mut mock_err, 1064 kill_on_drop: true, 1065 }; 1066 let _ = guard.poll_unpin(&mut context); 1067 } 1068 1069 assert_eq!(1, mock_pending.num_kills); 1070 assert_eq!(1, mock_pending.num_polls); 1071 1072 assert_eq!(0, mock_reaped.num_kills); 1073 assert_eq!(1, mock_reaped.num_polls); 1074 1075 assert_eq!(1, mock_err.num_kills); 1076 assert_eq!(1, mock_err.num_polls); 1077 } 1078 } 1079