From 1faaa91e5269b00b42e70f0a3b159fd7ba2ec520 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 28 Feb 2022 22:39:17 -0800 Subject: [PATCH] Avoid retaining executor in the FakeFs This probably isn't the *root* cause of why an executor is leaked, but by cutting off this cyclic references, it may make it a bit easier to track down leaks of an executor. --- crates/project/src/fs.rs | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/crates/project/src/fs.rs b/crates/project/src/fs.rs index 578be8cf82..9660312d5b 100644 --- a/crates/project/src/fs.rs +++ b/crates/project/src/fs.rs @@ -267,13 +267,13 @@ impl FakeFsState { pub struct FakeFs { // Use an unfair lock to ensure tests are deterministic. state: futures::lock::Mutex, - executor: std::sync::Arc, + executor: std::sync::Weak, } #[cfg(any(test, feature = "test-support"))] impl FakeFs { pub fn new(executor: std::sync::Arc) -> std::sync::Arc { - let (events_tx, _) = postage::broadcast::channel(2048); + let (events_tx, _) = postage::broadcast::channel(2); let mut entries = std::collections::BTreeMap::new(); entries.insert( Path::new("/").to_path_buf(), @@ -288,7 +288,7 @@ impl FakeFs { }, ); std::sync::Arc::new(Self { - executor, + executor: std::sync::Arc::downgrade(&executor), state: futures::lock::Mutex::new(FakeFsState { entries, next_inode: 1, @@ -375,13 +375,21 @@ impl FakeFs { } .boxed() } + + async fn simulate_random_delay(&self) { + self.executor + .upgrade() + .expect("excecutor has been dropped") + .simulate_random_delay() + .await; + } } #[cfg(any(test, feature = "test-support"))] #[async_trait::async_trait] impl Fs for FakeFs { async fn create_dir(&self, path: &Path) -> Result<()> { - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let state = &mut *self.state.lock().await; let path = normalize_path(path); let mut ancestor_path = PathBuf::new(); @@ -418,7 +426,7 @@ impl Fs for FakeFs { } async fn create_file(&self, path: &Path, options: CreateOptions) -> Result<()> { - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let mut state = self.state.lock().await; let path = normalize_path(path); state.validate_path(&path)?; @@ -546,7 +554,7 @@ impl Fs for FakeFs { async fn load(&self, path: &Path) -> Result { let path = normalize_path(path); - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let state = self.state.lock().await; let text = state .entries @@ -557,7 +565,7 @@ impl Fs for FakeFs { } async fn save(&self, path: &Path, text: &Rope) -> Result<()> { - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let mut state = self.state.lock().await; let path = normalize_path(path); state.validate_path(&path)?; @@ -589,13 +597,13 @@ impl Fs for FakeFs { } async fn canonicalize(&self, path: &Path) -> Result { - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; Ok(normalize_path(path)) } async fn is_file(&self, path: &Path) -> bool { let path = normalize_path(path); - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let state = self.state.lock().await; state .entries @@ -604,7 +612,7 @@ impl Fs for FakeFs { } async fn metadata(&self, path: &Path) -> Result> { - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let state = self.state.lock().await; let path = normalize_path(path); Ok(state.entries.get(&path).map(|entry| entry.metadata.clone())) @@ -615,7 +623,7 @@ impl Fs for FakeFs { abs_path: &Path, ) -> Result>>>> { use futures::{future, stream}; - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let state = self.state.lock().await; let abs_path = normalize_path(abs_path); Ok(Box::pin(stream::iter(state.entries.clone()).filter_map( @@ -635,7 +643,7 @@ impl Fs for FakeFs { _: Duration, ) -> Pin>>> { let state = self.state.lock().await; - self.executor.simulate_random_delay().await; + self.simulate_random_delay().await; let rx = state.events_tx.subscribe(); let path = path.to_path_buf(); Box::pin(futures::StreamExt::filter(rx, move |events| {