1 | #![warn (rust_2018_idioms)] |
2 | #![cfg (feature = "full" )] |
3 | #![cfg (unix)] |
4 | |
5 | use futures::future::join_all; |
6 | use std::process::Stdio; |
7 | use tokio::process::Command; |
8 | use tokio::task; |
9 | |
10 | #[tokio::test ] |
11 | async fn issue_42() { |
12 | // We spawn a many batches of processes which should exit at roughly the |
13 | // same time (modulo OS scheduling delays), to make sure that consuming |
14 | // a readiness event for one process doesn't inadvertently starve another. |
15 | // We then do this many times (in parallel) in an effort to stress test the |
16 | // implementation to ensure there are no race conditions. |
17 | // See alexcrichton/tokio-process#42 for background |
18 | let join_handles = (0..10usize).map(|_| { |
19 | task::spawn(async { |
20 | let processes = (0..10usize).map(|i| { |
21 | let mut child = Command::new("echo" ) |
22 | .arg(format!("I am spawned process #{}" , i)) |
23 | .stdin(Stdio::null()) |
24 | .stdout(Stdio::null()) |
25 | .stderr(Stdio::null()) |
26 | .kill_on_drop(true) |
27 | .spawn() |
28 | .unwrap(); |
29 | |
30 | async move { child.wait().await } |
31 | }); |
32 | |
33 | join_all(processes).await; |
34 | }) |
35 | }); |
36 | |
37 | join_all(join_handles).await; |
38 | } |
39 | |