From bacd17556741ab2fe05101a90f015861d9070ae4 Mon Sep 17 00:00:00 2001 From: Philip Degarmo Date: Wed, 18 Nov 2020 20:24:54 -0800 Subject: [PATCH] Fix a deadlock that can occur when using scope() on ComputeTaskPool from within a system. --- crates/bevy_tasks/src/task_pool.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/bevy_tasks/src/task_pool.rs b/crates/bevy_tasks/src/task_pool.rs index 7185dfb8614bb..4f82e02241203 100644 --- a/crates/bevy_tasks/src/task_pool.rs +++ b/crates/bevy_tasks/src/task_pool.rs @@ -194,7 +194,18 @@ impl TaskPool { let fut: Pin<&'static mut (dyn Future> + Send + 'static)> = unsafe { mem::transmute(fut) }; - future::block_on(self.executor.spawn(fut)) + // The thread that calls scope() will participate in driving tasks in the pool forward + // until the tasks that are spawned by this scope() call complete. (If the caller of scope() + // happens to be a thread in this thread pool, and we only have one thread in the pool, then + // simply calling future::block_on(spawned) would deadlock.) + let mut spawned = self.executor.spawn(fut); + loop { + if let Some(result) = future::block_on(future::poll_once(&mut spawned)) { + break result; + } + + self.executor.try_tick(); + } } /// Spawns a static future onto the thread pool. The returned Task is a future. It can also be