Skip to content

Commit

Permalink
gh-92530: Fix an issue that occurred after interrupting threading.Con…
Browse files Browse the repository at this point in the history
…dition.notify (GH-92534) (GH-92830)

If Condition.notify() was interrupted just after it released the waiter lock,
but before removing it from the queue, the following calls of notify() failed
with RuntimeError: cannot release un-acquired lock.
(cherry picked from commit 70af994)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
  • Loading branch information
miss-islington and serhiy-storchaka committed May 16, 2022
1 parent cfb9248 commit e29ce9a
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 7 deletions.
21 changes: 14 additions & 7 deletions Lib/threading.py
Expand Up @@ -368,14 +368,21 @@ def notify(self, n=1):
"""
if not self._is_owned():
raise RuntimeError("cannot notify on un-acquired lock")
all_waiters = self._waiters
waiters_to_notify = _deque(_islice(all_waiters, n))
if not waiters_to_notify:
return
for waiter in waiters_to_notify:
waiter.release()
waiters = self._waiters
while waiters and n > 0:
waiter = waiters[0]
try:
waiter.release()
except RuntimeError:
# gh-92530: The previous call of notify() released the lock,
# but was interrupted before removing it from the queue.
# It can happen if a signal handler raises an exception,
# like CTRL+C which raises KeyboardInterrupt.
pass
else:
n -= 1
try:
all_waiters.remove(waiter)
waiters.remove(waiter)
except ValueError:
pass

Expand Down
@@ -0,0 +1,2 @@
Fix an issue that occurred after interrupting
:func:`threading.Condition.notify`.

0 comments on commit e29ce9a

Please sign in to comment.