mirror of
https://github.com/python/cpython.git
synced 2025-07-30 06:34:15 +00:00
gh-92530: Fix an issue that occurred after interrupting threading.Condition.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 70af994fee
)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
cfb9248cd4
commit
e29ce9a5f1
2 changed files with 16 additions and 7 deletions
|
@ -368,14 +368,21 @@ class Condition:
|
||||||
"""
|
"""
|
||||||
if not self._is_owned():
|
if not self._is_owned():
|
||||||
raise RuntimeError("cannot notify on un-acquired lock")
|
raise RuntimeError("cannot notify on un-acquired lock")
|
||||||
all_waiters = self._waiters
|
waiters = self._waiters
|
||||||
waiters_to_notify = _deque(_islice(all_waiters, n))
|
while waiters and n > 0:
|
||||||
if not waiters_to_notify:
|
waiter = waiters[0]
|
||||||
return
|
|
||||||
for waiter in waiters_to_notify:
|
|
||||||
waiter.release()
|
|
||||||
try:
|
try:
|
||||||
all_waiters.remove(waiter)
|
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:
|
||||||
|
waiters.remove(waiter)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix an issue that occurred after interrupting
|
||||||
|
:func:`threading.Condition.notify`.
|
Loading…
Add table
Add a link
Reference in a new issue