@@ -418,6 +418,17 @@ def test_unacquired_notify(self):
418418 self .assertRaises (RuntimeError , cond .notify )
419419
420420 def _check_notify (self , cond ):
421+ # Note that this test is sensitive to timing. If the worker threads
422+ # don't execute in a timely fashion, the main thread may think they
423+ # are further along then they are. The main thread therefore issues
424+ # _wait() statements to try to make sure that it doesn't race ahead
425+ # of the workers.
426+ # Secondly, this test assumes that condition variables are not subject
427+ # to spurious wakeups. The absence of spurious wakeups is an implementation
428+ # detail of Condition Cariables in current CPython, but in general, not
429+ # a guaranteed property of condition variables as a programming
430+ # construct. In particular, it is possible that this can no longer
431+ # be conveniently guaranteed should their implementation ever change.
421432 N = 5
422433 results1 = []
423434 results2 = []
@@ -445,6 +456,9 @@ def f():
445456 _wait ()
446457 self .assertEqual (results1 , [(True , 1 )] * 3 )
447458 self .assertEqual (results2 , [])
459+ # first wait, to ensure all workers settle into cond.wait() before
460+ # we continue. See issue #8799
461+ _wait ()
448462 # Notify 5 threads: they might be in their first or second wait
449463 cond .acquire ()
450464 cond .notify (5 )
@@ -455,6 +469,7 @@ def f():
455469 _wait ()
456470 self .assertEqual (results1 , [(True , 1 )] * 3 + [(True , 2 )] * 2 )
457471 self .assertEqual (results2 , [(True , 2 )] * 3 )
472+ _wait () # make sure all workers settle into cond.wait()
458473 # Notify all threads: they are all in their second wait
459474 cond .acquire ()
460475 cond .notify_all ()
0 commit comments