Skip to content

Commit 38d95b5

Browse files
[3.11] gh-92530: Fix an issue that occurred after interrupting threading.Condition.notify (GH-92534) (GH-92829)
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 <[email protected]> Automerge-Triggered-By: GH:serhiy-storchaka
1 parent 76b81be commit 38d95b5

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

Lib/threading.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -368,14 +368,21 @@ def notify(self, n=1):
368368
"""
369369
if not self._is_owned():
370370
raise RuntimeError("cannot notify on un-acquired lock")
371-
all_waiters = self._waiters
372-
waiters_to_notify = _deque(_islice(all_waiters, n))
373-
if not waiters_to_notify:
374-
return
375-
for waiter in waiters_to_notify:
376-
waiter.release()
371+
waiters = self._waiters
372+
while waiters and n > 0:
373+
waiter = waiters[0]
374+
try:
375+
waiter.release()
376+
except RuntimeError:
377+
# gh-92530: The previous call of notify() released the lock,
378+
# but was interrupted before removing it from the queue.
379+
# It can happen if a signal handler raises an exception,
380+
# like CTRL+C which raises KeyboardInterrupt.
381+
pass
382+
else:
383+
n -= 1
377384
try:
378-
all_waiters.remove(waiter)
385+
waiters.remove(waiter)
379386
except ValueError:
380387
pass
381388

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix an issue that occurred after interrupting
2+
:func:`threading.Condition.notify`.

0 commit comments

Comments
 (0)