Skip to content

Commit e41847a

Browse files
authored
ex: Add example for timed out process (#38)
1 parent 9f57bbf commit e41847a

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@ features = [
4343
"Win32_System_Threading",
4444
"Win32_System_WindowsProgramming"
4545
]
46+
47+
[dev-dependencies]
48+
async-io = "1.8"

examples/timeout.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! An example of running a `Command` with a timeout.
2+
3+
use async_io::Timer;
4+
use async_process::{Command, Stdio};
5+
use futures_lite::{future, prelude::*};
6+
use std::io;
7+
8+
fn main() -> io::Result<()> {
9+
async_io::block_on(async {
10+
// Spawn a a command of your choice.
11+
let mut child = Command::new("sleep")
12+
.arg("3")
13+
.stdout(Stdio::piped())
14+
.stderr(Stdio::piped())
15+
.spawn()?;
16+
17+
// Run a future to drain the stdout of the child.
18+
// We can't use output() here because it would be cancelled along with the child when the timeout
19+
// expires.
20+
let mut stdout = String::new();
21+
let drain_stdout = {
22+
let buffer = &mut stdout;
23+
let mut stdout = child.stdout.take().unwrap();
24+
25+
async move {
26+
stdout.read_to_string(buffer).await?;
27+
28+
// Wait for the child to exit or the timeout.
29+
future::pending().await
30+
}
31+
};
32+
33+
// Run a future to drain the stderr of the child.
34+
let mut stderr = String::new();
35+
let drain_stderr = {
36+
let buffer = &mut stderr;
37+
let mut stderr = child.stderr.take().unwrap();
38+
39+
async move {
40+
stderr.read_to_string(buffer).await?;
41+
42+
// Wait for the child to exit or the timeout.
43+
future::pending().await
44+
}
45+
};
46+
47+
// Run a future that waits for the child to exit.
48+
let wait = async move {
49+
child.status().await?;
50+
51+
// Child exited.
52+
io::Result::Ok(false)
53+
};
54+
55+
// Run a future that times out after 5 seconds.
56+
let timeout_s = 1;
57+
let timeout = async move {
58+
Timer::after(std::time::Duration::from_secs(timeout_s)).await;
59+
60+
// Timed out.
61+
Ok(true)
62+
};
63+
64+
// Run the futures concurrently.
65+
// Note: For larger scale programs than this you should probably spawn each individual future on
66+
// a separate task in an executor.
67+
let timed_out = drain_stdout.or(drain_stderr).or(wait).or(timeout).await?;
68+
69+
if timed_out {
70+
println!("The child timed out.");
71+
} else {
72+
println!("The child exited.");
73+
}
74+
75+
println!("Stdout:\n{}", stdout);
76+
println!("Stderr:\n{}", stderr);
77+
78+
Ok(())
79+
})
80+
}

0 commit comments

Comments
 (0)