Parallel runner deadlocks with idling threads in ComputeTaskPool
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## Bevy version
0.6.0
## Operating system & version
Windows 11
## What you did
```rs
let mut app = App::new();
app.insert_resource(bevy_tasks::ComputeTaskPool(
bevy_tasks::TaskPoolBuilder::new().num_threads(1).build(),
));
let a = Arc::new(FairMutex::new(0usize));
let b = Arc::new(FairMutex::new(0usize));
let c = Arc::new(FairMutex::new(0usize));
let set = SystemSet::new()
.with_system({
let a = Arc::clone(&a);
(move || {
tracing::info!(
thread_id = format_args!("{:?}", std::thread::current()),
"A incrementing"
);
*a.lock() += 1;
})
})
.with_system({
let b = Arc::clone(&b);
(move || {
tracing::info!(
thread_id = format_args!("{:?}", std::thread::current()),
"B incrementing"
);
*b.lock() += 1;
})
})
.with_system(
(move || {
tracing::info!(thread_id = format_args!("{:?}", std::thread::current()), "C spinning");
let mut c = c.lock();
*c += 1;
while *a.lock() != *c || *b.lock() != *c {}
}),
);
app.add_system_set_to_stage(CoreStage::Update, set);
for ix in 0..500 {
let _span = tracing::info_span!("iteration", ix).entered();
app.update();
}
```
## What you expected to happen
With the main thread + one more thread in the task pool, this should be completeable regardless of execution order.
## What actually happened
It deadlocks after a number of iterations, here's a snapshot of the tracing logs (only the last entries):
```
...
2022-03-09T00:54:16.833550Z INFO repro: C spinning, thread_id: Thread { id: ThreadId(1), name: Some("main"), .. }
at src/main.rs:123
in bevy_ecs::schedule::executor_parallel::system with name: "repro::main::{{closure}}"
in bevy_ecs::schedule::executor_parallel::prepare_systems
in bevy_ecs::schedule::stage with name: Update
in repro::iteration with ix: 182
2022-03-09T00:54:16.833562Z INFO repro: A incrementing, thread_id: Thread { id: ThreadId(2), name: Some("TaskPool (0)"), .. }
at src/main.rs:104
in bevy_ecs::schedule::executor_parallel::system with name: "repro::main::{{closure}}"
in bevy_ecs::schedule::executor_parallel::prepare_systems
in bevy_ecs::schedule::stage with name: Update
in repro::iteration with ix: 182
2022-03-09T00:54:16.834361Z INFO repro: B incrementing, thread_id: Thread { id: ThreadId(2), name: Some("TaskPool (0)"), .. }
at src/main.rs:114
in bevy_ecs::schedule::executor_parallel::system with name: "repro::main::{{closure}}"
in bevy_ecs::schedule::executor_parallel::prepare_systems
in bevy_ecs::schedule::stage with name: Update
in repro::iteration with ix: 182
2022-03-09T00:54:16.835071Z INFO repro: B incrementing, thread_id: Thread { id: ThreadId(1), name: Some("main"), .. }
at src/main.rs:114
in bevy_ecs::schedule::executor_parallel::system with name: "repro::main::{{closure}}"
in bevy_ecs::schedule::executor_parallel::prepare_systems
in bevy_ecs::schedule::stage with name: Update
in repro::iteration with ix: 183
2022-03-09T00:54:16.835076Z INFO repro: C spinning, thread_id: Thread { id: ThreadId(2), name: Some("TaskPool (0)"), .. }
at src/main.rs:123
in bevy_ecs::schedule::executor_parallel::system with name: "repro::main::{{closure}}"
in bevy_ecs::schedule::executor_parallel::prepare_systems
in bevy_ecs::schedule::stage with name: Update
in repro::iteration with ix: 183
```
These logs show a successful iteration (there were 181 more before it), followed by a deadlock which I exited out after waiting a couple of seconds.
Contributor guide
Research direction
Reproduce the one-thread ComputeTaskPool case using the TaskPoolBuilder setup in the issue, then inspect the bevy_ecs::schedule::executor_parallel path named in the trace. Compare the successful and deadlocking iterations and add a regression test if the relevant test location becomes clear. Done means the 500 updates complete without deadlocking.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- distributed-systems, game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100