You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is a race between when Thread._tstate_lock is released1 in Thread._wait_for_tstate_lock() and when Thread._stop() asserts2 that it is unlocked. Consider the following execution involving threads A, B, and C:
A starts.
B joins A, blocking on its _tstate_lock.
C joins A, blocking on its _tstate_lock.
A finishes and releases its _tstate_lock.
B acquires A's _tstate_lock in _wait_for_tstate_lock(), releases it, but is swapped out before calling _stop().
C is scheduled, acquires A's _tstate_lock in _wait_for_tstate_lock() but is swapped out before releasing it.
B is scheduled, calls _stop(), which asserts that A's _tstate_lock is not held. However, C holds it, so the assertion fails.
The race can be reproduced3 by inserting sleeps at the appropriate points in the threading code. To do so, run the repro_join_race.py from the linked repo.
Activity