Bug report
Bug description:
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.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Bug report
Bug description:
There is a race between when
Thread._tstate_lockis released1 inThread._wait_for_tstate_lock()and whenThread._stop()asserts2 that it is unlocked. Consider the following execution involving threads A, B, and C:_tstate_lock._tstate_lock._tstate_lock._tstate_lockin_wait_for_tstate_lock(), releases it, but is swapped out before calling_stop()._tstate_lockin_wait_for_tstate_lock()but is swapped out before releasing it._stop(), which asserts that A's_tstate_lockis 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.pyfrom the linked repo.CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Footnotes
https://github.com/python/cpython/blob/441affc9e7f419ef0b68f734505fa2f79fe653c7/Lib/threading.py#L1201 ↩
https://github.com/python/cpython/blob/441affc9e7f419ef0b68f734505fa2f79fe653c7/Lib/threading.py#L1115 ↩
https://github.com/mpage/cpython/commit/81946532792f938cd6f6ab4c4ff92a4edf61314f ↩