diff options
author | Charles-François Natali <neologix@free.fr> | 2012-01-07 17:24:56 (GMT) |
---|---|---|
committer | Charles-François Natali <neologix@free.fr> | 2012-01-07 17:24:56 (GMT) |
commit | ded0348c08f298fda4426eb2a62cc3d50eed25b5 (patch) | |
tree | f762e7f1f50cce89494a53a5744ad307d0d02b2d | |
parent | b52e7a9a364096d355d32927c537389cfc10a5db (diff) | |
download | cpython-ded0348c08f298fda4426eb2a62cc3d50eed25b5.zip cpython-ded0348c08f298fda4426eb2a62cc3d50eed25b5.tar.gz cpython-ded0348c08f298fda4426eb2a62cc3d50eed25b5.tar.bz2 |
Issue #13502: threading: Fix a race condition in Event.wait() that made it
return False when the event was set and cleared right after.
-rw-r--r-- | Doc/library/threading.rst | 6 | ||||
-rw-r--r-- | Lib/test/lock_tests.py | 16 | ||||
-rw-r--r-- | Lib/threading.py | 7 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
4 files changed, 27 insertions, 5 deletions
diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index c226dd4..9b3affd 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -782,8 +782,10 @@ An event object manages an internal flag that can be set to true with the 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 index 30148e6..094cc7a 100644 --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -351,6 +351,22 @@ class EventTests(BaseTestCase): 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 index 043e6c8..fe92f10 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -418,9 +418,10 @@ class _Event(_Verbose): 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() @@ -97,6 +97,9 @@ Core and Builtins 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 #12926: Fix a bug in tarfile's link extraction. - Issue #13696: Fix the 302 Relative URL Redirection problem. |