diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index efc464f4032026..46ff753df08f8c 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -347,6 +347,17 @@ def test_unacquired_notify(self): self.assertRaises(RuntimeError, cond.notify) def _check_notify(self, cond): + # Note that this test is sensitive to timing. If the worker threads + # don't execute in a timely fashion, the main thread may think they + # are further along then they are. The main thread therefore issues + # _wait() statements to try to make sure that it doesn't race ahead + # of the workers. + # Secondly, this test assumes that condition variables are not subject + # to spurious wakeups. The absence of spurious wakeups is an implementation + # detail of Condition Cariables in current CPython, but in general, not + # a guaranteed property of condition variables as a programming + # construct. In particular, it is possible that this can no longer + # be conveniently guaranteed should their implementation ever change. N = 5 results1 = [] results2 = [] @@ -374,6 +385,9 @@ def f(): _wait() self.assertEqual(results1, [1] * 3) self.assertEqual(results2, []) + # first wait, to ensure all workers settle into cond.wait() before + # we continue. See issue #8799 + _wait() # Notify 5 threads: they might be in their first or second wait cond.acquire() cond.notify(5) @@ -384,6 +398,7 @@ def f(): _wait() self.assertEqual(results1, [1] * 3 + [2] * 2) self.assertEqual(results2, [2] * 3) + _wait() # make sure all workers settle into cond.wait() # Notify all threads: they are all in their second wait cond.acquire() cond.notify_all()