tokio::select!
blocks when using tokio::io::Lines::next_line()
#5684
-
I've just encountered this, and I'm not sure if it's a bug, or if it's some API I've misunderstood... Basically, I have two futures I'm trying to run at the same time, and I want to get the first one that errors (and cancel all the rest). I'm trying to do this with According to its documentation, I've pushed a small reproducible repo here: https://github.com/acheronfail/tokio-select-example #[tokio::main(flavor = "current_thread")]
async fn main() {
let result = tokio::select! {
err = stdin_lines() => err,
err = error() => err,
};
match result {
Ok(_) => unreachable!(),
Err(e) => println!("error: {}", e),
}
}
async fn stdin_lines() -> Result<std::convert::Infallible, Box<dyn std::error::Error>> {
use tokio::io::AsyncBufReadExt;
let stdin = tokio::io::BufReader::new(tokio::io::stdin());
let mut lines = stdin.lines();
loop {
let _ = lines.next_line().await?.unwrap();
}
}
async fn error() -> Result<std::convert::Infallible, Box<dyn std::error::Error>> {
println!("erroring in 1 second...");
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
println!("erroring now");
Err("boom".into())
} I run this example like this: $ cargo build;
$ cat | (./target/debug/tokio-select-example; echo exited with: $?) Wait for it to error, and you will observe that the program will not exit until two lines have been read. What I expected
So, in this example, I expected: $ cat | (./target/debug/tokio-select-example; echo exited with: $?)
erroring in 1 second...
erroring now
error: boom
exited with: 0 # <-- I expected the program to EXIT
$ What I'm seeing
$ cat | (./target/debug/tokio-select-example; echo exited with: $?)
erroring in 1 second...
erroring now
error: boom
asdf # <-- the program hangs until a new line is entered
exited with: 0
$ |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
When you return from I recommend following the recommendation from the documentation:
|
Beta Was this translation helpful? Give feedback.
When you return from
main
, Tokio will attempt to kill and then wait for background tasks before it exits. However, the background task that reads from stdin is impossible to kill, so Tokio is forced to wait until it returns normally.I recommend following the recommendation from the documentation: