[Python-checkins] cpython (merge 3.2 -> default): Issue #13502: threading: Fix a race condition in Event.wait() that made it

charles-francois.natali python-checkins at python.org
Sat Jan 7 18:27:06 CET 2012


http://hg.python.org/cpython/rev/0fe63bb20e74
changeset:   74293:0fe63bb20e74
parent:      74291:9f0728521731
parent:      74292:eb39d862a250
user:        Charles-François Natali <neologix at free.fr>
date:        Sat Jan 07 18:26:39 2012 +0100
summary:
  Issue #13502: threading: Fix a race condition in Event.wait() that made it
return False when the event was set and cleared right after.

files:
  Doc/library/threading.rst |   6 ++++--
  Lib/test/lock_tests.py    |  16 ++++++++++++++++
  Lib/threading.py          |   7 ++++---
  Misc/NEWS                 |   3 +++
  4 files changed, 27 insertions(+), 5 deletions(-)


diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst
--- a/Doc/library/threading.rst
+++ b/Doc/library/threading.rst
@@ -804,8 +804,10 @@
       floating point number specifying a timeout for the operation in seconds
       (or fractions thereof).
 
-      This method returns the internal flag on exit, so it will always return
-      ``True`` except if a timeout is given and the operation times out.
+      This method returns true if and only if the internal flag has been set to
+      true, either before the wait call or after the wait starts, so it will
+      always return ``True`` except if a timeout is given and the operation
+      times out.
 
       .. versionchanged:: 3.1
          Previously, the method always returned ``None``.
diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py
--- a/Lib/test/lock_tests.py
+++ b/Lib/test/lock_tests.py
@@ -353,6 +353,22 @@
         for r, dt in results2:
             self.assertTrue(r)
 
+    def test_set_and_clear(self):
+        # Issue #13502: check that wait() returns true even when the event is
+        # cleared before the waiting thread is woken up.
+        evt = self.eventtype()
+        results = []
+        N = 5
+        def f():
+            results.append(evt.wait(1))
+        b = Bunch(f, N)
+        b.wait_for_started()
+        time.sleep(0.5)
+        evt.set()
+        evt.clear()
+        b.wait_for_finished()
+        self.assertEqual(results, [True] * N)
+
 
 class ConditionTests(BaseTestCase):
     """
diff --git a/Lib/threading.py b/Lib/threading.py
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -408,9 +408,10 @@
     def wait(self, timeout=None):
         self._cond.acquire()
         try:
-            if not self._flag:
-                self._cond.wait(timeout)
-            return self._flag
+            signaled = self._flag
+            if not signaled:
+                signaled = self._cond.wait(timeout)
+            return signaled
         finally:
             self._cond.release()
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -422,6 +422,9 @@
 Library
 -------
 
+- Issue #13502: threading: Fix a race condition in Event.wait() that made it
+  return False when the event was set and cleared right after.
+
 - Issue #9993: When the source and destination are on different filesystems,
   and the source is a symlink, shutil.move() now recreates a symlink on the
   destination instead of copying the file contents.  Patch by Jonathan Niehof

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list