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