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