From c56e2ead23128c427d7e4ac62d3755625227df69 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Apr 2022 13:25:21 -0700 Subject: [PATCH] Fix hang when dropping ::scoped future under deterministic executor Co-authored-by: Nathan Sobo Co-authored-by: Keith Simmons --- crates/gpui/src/executor.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/gpui/src/executor.rs b/crates/gpui/src/executor.rs index 6d8e946f589a44f521b71596501b4a23ab5d59a6..24ab663071b4c47da2468763d41994e9068ea2b2 100644 --- a/crates/gpui/src/executor.rs +++ b/crates/gpui/src/executor.rs @@ -1,5 +1,6 @@ use anyhow::{anyhow, Result}; use async_task::Runnable; +use futures::channel::mpsc; use smol::{channel, prelude::*, Executor}; use std::{ any::Any, @@ -8,7 +9,7 @@ use std::{ mem, pin::Pin, rc::Rc, - sync::{mpsc, Arc}, + sync::Arc, task::{Context, Poll}, thread, time::Duration, @@ -621,11 +622,11 @@ impl Background { Err(async { *future.await.downcast().unwrap() }) } - pub async fn scoped<'scope, F>(&self, scheduler: F) + pub async fn scoped<'scope, F>(self: &Arc, scheduler: F) where F: FnOnce(&mut Scope<'scope>), { - let mut scope = Scope::new(); + let mut scope = Scope::new(self.clone()); (scheduler)(&mut scope); let spawned = mem::take(&mut scope.futures) .into_iter() @@ -664,6 +665,7 @@ impl Background { } pub struct Scope<'a> { + executor: Arc, futures: Vec + Send + 'static>>>, tx: Option>, rx: mpsc::Receiver<()>, @@ -671,9 +673,10 @@ pub struct Scope<'a> { } impl<'a> Scope<'a> { - fn new() -> Self { - let (tx, rx) = mpsc::channel(); + fn new(executor: Arc) -> Self { + let (tx, rx) = mpsc::channel(1); Self { + executor, tx: Some(tx), rx, futures: Default::default(), @@ -708,7 +711,7 @@ impl<'a> Drop for Scope<'a> { // Wait until the channel is closed, which means that all of the spawned // futures have resolved. - self.rx.recv().ok(); + self.executor.block(self.rx.next()); } }