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