From 0dc3966dc4ad4fbfaf38816ec732e5ba2733a1de Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 14 Jan 2025 13:17:16 -0600 Subject: [PATCH] Fix dropping cached stack with `Store::into_data` (#10009) This commit fixes a regression from #9604 where using `Store::into_data` wouldn't properly drop a cached stack in a store like a `Drop` destructor. The fix here is to add the `flush_fiber_stack` method into the `into_data` here as well. --- crates/wasmtime/src/runtime/store.rs | 2 ++ tests/all/pooling_allocator.rs | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs index 7651c7900a88..a8e579ecbf76 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -643,6 +643,8 @@ impl Store { /// Consumes this [`Store`], destroying it, and returns the underlying data. pub fn into_data(mut self) -> T { + self.inner.flush_fiber_stack(); + // This is an unsafe operation because we want to avoid having a runtime // check or boolean for whether the data is actually contained within a // `Store`. The data itself is stored as `ManuallyDrop` since we're diff --git a/tests/all/pooling_allocator.rs b/tests/all/pooling_allocator.rs index 1fbb138c8c02..ce73da61eec8 100644 --- a/tests/all/pooling_allocator.rs +++ b/tests/all/pooling_allocator.rs @@ -995,16 +995,21 @@ async fn total_stacks_limit() -> Result<()> { let mut store1 = Store::new(&engine, ()); let instance1 = linker.instantiate_async(&mut store1, &module).await?; let run1 = instance1.get_func(&mut store1, "run").unwrap(); - let future1 = run1.call_async(store1, &[], &mut []); + let future1 = run1.call_async(&mut store1, &[], &mut []); let mut store2 = Store::new(&engine, ()); let instance2 = linker.instantiate_async(&mut store2, &module).await?; let run2 = instance2.get_func(&mut store2, "run").unwrap(); - let future2 = run2.call_async(store2, &[], &mut []); + let future2 = run2.call_async(&mut store2, &[], &mut []); future1.await?; future2.await?; + // Dispose one store via `Drop`, the other via `into_data`, and ensure that + // any lingering stacks make their way back to the pool. + drop(store1); + store2.into_data(); + Ok(()) }