Skip to content

Commit 14d0594

Browse files
gh-92530: Fix an issue that occurred after interrupting threading.Condition.notify (GH-92534) (GH-92831)
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]>
1 parent c4fc53f commit 14d0594

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
@@ -360,14 +360,21 @@ def notify(self, n=1):
360360
"""
361361
if not self._is_owned():
362362
raise RuntimeError("cannot notify on un-acquired lock")
363-
all_waiters = self._waiters
364-
waiters_to_notify = _deque(_islice(all_waiters, n))
365-
if not waiters_to_notify:
366-
return
367-
for waiter in waiters_to_notify:
368-
waiter.release()
363+
waiters = self._waiters
364+
while waiters and n > 0:
365+
waiter = waiters[0]
366+
try:
367+
waiter.release()
368+
except RuntimeError:
369+
# gh-92530: The previous call of notify() released the lock,
370+
# but was interrupted before removing it from the queue.
371+
# It can happen if a signal handler raises an exception,
372+
# like CTRL+C which raises KeyboardInterrupt.
373+
pass
374+
else:
375+
n -= 1
369376
try:
370-
all_waiters.remove(waiter)
377+
waiters.remove(waiter)
371378
except ValueError:
372379
pass
373380

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)