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