From 020af2a2bc4708215360a3793b5a1790e15d05dd Mon Sep 17 00:00:00 2001
From: Kristjan Valur Jonsson <sweskman@gmail.com>
Date: Mon, 11 Nov 2013 11:29:04 +0000
Subject: Issue #8799: Reduce timing sensitivity of condition test by
 explicitly delaying the main thread so that it doesn't race ahead of the
 workers.

---
 Lib/test/lock_tests.py | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py
index 1a24bde..1cbcea2 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()
-- 
cgit v0.12