mirror of https://github.com/python/cpython
bpo-45274: Fix Thread._wait_for_tstate_lock() race condition (GH-28532)
Fix a race condition in the Thread.join() method of the threading module. If the function is interrupted by a signal and the signal handler raises an exception, make sure that the thread remains in a consistent state to prevent a deadlock.
This commit is contained in:
parent
7b88f63e1d
commit
a22be4943c
|
@ -1094,11 +1094,24 @@ class Thread:
|
|||
# If the lock is acquired, the C code is done, and self._stop() is
|
||||
# called. That sets ._is_stopped to True, and ._tstate_lock to None.
|
||||
lock = self._tstate_lock
|
||||
if lock is None: # already determined that the C code is done
|
||||
if lock is None:
|
||||
# already determined that the C code is done
|
||||
assert self._is_stopped
|
||||
elif lock.acquire(block, timeout):
|
||||
lock.release()
|
||||
self._stop()
|
||||
return
|
||||
|
||||
try:
|
||||
if lock.acquire(block, timeout):
|
||||
lock.release()
|
||||
self._stop()
|
||||
except:
|
||||
if lock.locked():
|
||||
# bpo-45274: lock.acquire() acquired the lock, but the function
|
||||
# was interrupted with an exception before reaching the
|
||||
# lock.release(). It can happen if a signal handler raises an
|
||||
# exception, like CTRL+C which raises KeyboardInterrupt.
|
||||
lock.release()
|
||||
self._stop()
|
||||
raise
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
Fix a race condition in the :meth:`Thread.join() <threading.Thread.join>`
|
||||
method of the :mod:`threading` module. If the function is interrupted by a
|
||||
signal and the signal handler raises an exception, make sure that the thread
|
||||
remains in a consistent state to prevent a deadlock. Patch by Victor
|
||||
Stinner.
|
Loading…
Reference in New Issue