From cdd6c232533af188135969c8e782ef7c8f570b94 Mon Sep 17 00:00:00 2001 From: James Braid Date: Sat, 7 Nov 2026 03:16:45 -0700 Subject: [PATCH] wd33c93a: stop the worker without losing its wakeup The worker checks `running` with the state lock held and then waits on the condition variable, which releases the lock. stop() cleared `running` and notified without taking that lock, so a stop landing between the worker's check and its wait woke nobody: the worker slept on, and the join in stop() waited forever. A stopping machine hung in Hpc3::stop with the WD33C93A thread parked in its wait (seen in stopping_the_disks_comes_before_stopping_the_graphics, twice in about 130 lib test runs at 224 test threads). Clear `running` under the lock. --- src/dev/wd33c93a.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/dev/wd33c93a.rs b/src/dev/wd33c93a.rs index e9dd5657a..58c5b4ceb 100644 --- a/src/dev/wd33c93a.rs +++ b/src/dev/wd33c93a.rs @@ -821,7 +821,13 @@ impl FifoDevice for Wd33c93a { impl Device for Wd33c93a { fn step(&self, _cycles: u64) {} fn stop(&self) { - self.running.store(false, Ordering::SeqCst); + // Under the state lock: the worker checks `running` holding it and + // then waits, so a store and notify between the two would be lost + // and the join below would wait forever. + { + let _state = self.state.lock(); + self.running.store(false, Ordering::SeqCst); + } self.cond.notify_all(); if let Some(t) = self.thread.lock().take() { let _ = t.join();