From f2b6449c9fd78f18e791b904fa38bccd51f444e5 Mon Sep 17 00:00:00 2001 From: Sebastian Urban Date: Wed, 18 Dec 2024 12:06:22 +0100 Subject: [PATCH] Fix thread parking on WebAssembly On WebAssembly the notification state was not checked before sleeping and thus wrongfully ignored. Additionally this refines the check whether threads are available on a particular WebAssembly target. --- tokio/src/runtime/park.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tokio/src/runtime/park.rs b/tokio/src/runtime/park.rs index c260b7512be..c5c8b1307d0 100644 --- a/tokio/src/runtime/park.rs +++ b/tokio/src/runtime/park.rs @@ -65,12 +65,7 @@ impl ParkThread { pub(crate) fn park_timeout(&mut self, duration: Duration) { #[cfg(loom)] CURRENT_THREAD_PARK_COUNT.with(|count| count.fetch_add(1, SeqCst)); - - // Wasm doesn't have threads, so just sleep. - #[cfg(not(target_family = "wasm"))] self.inner.park_timeout(duration); - #[cfg(target_family = "wasm")] - std::thread::sleep(duration); } pub(crate) fn shutdown(&mut self) { @@ -158,12 +153,20 @@ impl Inner { Err(actual) => panic!("inconsistent park_timeout state; actual = {actual}"), } + #[cfg(not(all(target_family = "wasm", not(target_feature = "atomics"))))] // Wait with a timeout, and if we spuriously wake up or otherwise wake up // from a notification, we just want to unconditionally set the state back to // empty, either consuming a notification or un-flagging ourselves as // parked. let (_m, _result) = self.condvar.wait_timeout(m, dur).unwrap(); + #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] + // Wasm without atomics doesn't have threads, so just sleep. + { + let _m = m; + std::thread::sleep(dur); + } + match self.state.swap(EMPTY, SeqCst) { NOTIFIED => {} // got a notification, hurray! PARKED => {} // no notification, alas