https://github.com/python/cpython/commit/2012d35281f2f2004dd37f10f49eb56688a60e98 commit: 2012d35281f2f2004dd37f10f49eb56688a60e98 branch: 3.14 author: Miss Islington (bot) <[email protected]> committer: vstinner <[email protected]> date: 2026-11-09T16:34:30Z summary:
[3.14] gh-158336: Fix race in lock_tests test_set_and_clear (GH-158337) (#161683) gh-158336: Fix race in lock_tests test_set_and_clear (GH-158337) test_set_and_clear() started N threads calling event.wait() and then slept 50 ms (wait_threads_blocked) before calling event.set() and event.clear(). If a thread only reached wait() after clear(), it saw the flag unset and blocked for LONG_TIMEOUT, and Bunch.__exit__ gave up after SHORT_TIMEOUT. This happened on CI in the TSan free-threading job. Wait until all N threads are in the Condition's waiter list instead. Condition.wait() appends the waiter while holding the lock, and notify_all() releases every waiter in the list, so each of those threads is guaranteed to be woken by set(). On a TSan free-threading debug build, pinned to 2 CPUs shared with 4 busy-looping processes, the test failed in 9 of 40 runs before this change and 0 of 40 after. (cherry picked from commit 9e220787624afba3e20f0067da6dee3e50fcc008) Co-authored-by: Matthias Görgens <[email protected]> Co-authored-by: Victor Stinner <[email protected]> files: M Lib/test/lock_tests.py diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index 1a41fd3f1ddb4d..fc035abf158cda 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -561,6 +561,8 @@ def test_nan_timeout(self): evt = self.eventtype() self.assertRaises(ValueError, evt.wait, float('nan')) + # Use private attributes (event._cond._waiters) + @support.cpython_only def test_set_and_clear(self): # gh-57711: check that wait() returns true even when the event is # cleared before the waiting thread is woken up. @@ -571,8 +573,11 @@ def f(): N = 5 with Bunch(f, N): - # Threads blocked on event.wait() - wait_threads_blocked(N) + # Wait until all threads are registered as waiters in + # event.wait(). + for _ in support.sleeping_retry(support.SHORT_TIMEOUT): + if len(event._cond._waiters) >= N: + break # Threads unblocked event.set() _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
