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,9 @@ 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 by another thread, 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()