From cf75c22c9aa76b6d7e0ffed06c78d99a4c951436 Mon Sep 17 00:00:00 2001 From: Philip Degarmo Date: Wed, 25 Nov 2020 18:05:55 -0800 Subject: [PATCH] Fix a deadlock that can occur when using scope() on ComputeTaskPool from within a system. (#892) --- 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