Tokio select! Macro Issue with Barrier
suxb201 opened this issue · comments
suxb201 commented
Version
tokio v1.37.0
tokio-macros v2.2.0 (proc-macro)
Platform
Darwin Kernel Version 23.0.0
Description
The Barrier
implementation might be incrementing the state.generation
field every time the select!
is called.
I tried this code:
use tokio;
use std::sync::Arc;
use tokio::select;
use tokio::time::sleep;
use tokio::sync::Barrier;
use tokio::task::JoinSet;
#[tokio::main]
async fn main() {
let barrier = Arc::new(Barrier::new(2));
let mut tasks = JoinSet::new();
tasks.spawn({
let barrier = barrier.clone();
async move {
loop {
sleep(std::time::Duration::from_secs(1)).await;
barrier.wait().await;
}
}
});
tasks.spawn(async move {
let mut interval = tokio::time::interval(std::time::Duration::from_secs(1));
loop {
select! {
_ = interval.tick() => {
println ! ("interval tick");
}
_ = barrier.wait() => {
println ! ("barrier wait");
}
}
}
});
for _ in 0..2 {
tasks.join_next().await;
}
}
I expected to see this happen:
interval tick
barrier wait
interval tick
barrier wait
interval tick
barrier wait
...
Instead, this happened:
interval tick
barrier wait
barrier wait
interval tick
barrier wait
barrier wait
interval tick
barrier wait
barrier wait
...
Alice Ryhl commented
Thank you for reporting this. Barriers are not cancel safe, so you can't use them in a tokio::select!
like that. Unfortunately, fixing this would take a breaking change.
I have opened #6494 to document this issue.