diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py index 1a24bdeed37..1cbcea23439 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -418,6 +418,17 @@ class ConditionTests(BaseTestCase): 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 = [] @@ -445,6 +456,9 @@ class ConditionTests(BaseTestCase): _wait() self.assertEqual(results1, [(True, 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) @@ -455,6 +469,7 @@ class ConditionTests(BaseTestCase): _wait() self.assertEqual(results1, [(True, 1)] * 3 + [(True, 2)] * 2) self.assertEqual(results2, [(True, 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()