Skip to content

Parallel runner deadlocks with idling threads in ComputeTaskPool #4161

@farnoy

Description

@farnoy

Bevy version

0.6.0

Operating system & version

Windows 11

What you did

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-TasksTools for parallel and async workC-BugAn unexpected or incorrect behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions