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:
Miss Islington (bot) 2022-05-16 09:54:01 -07:00 committed by GitHub
parent cfb9248cd4
commit e29ce9a5f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 7 deletions

View file

@ -368,14 +368,21 @@ class Condition:
"""
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:
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:
pass