gh-119585: Fix crash involving PyGILState_Release() and PyThreadState_Clear() (#119753)

Make sure that `gilstate_counter` is not zero in when calling
`PyThreadState_Clear()`. A destructor called from `PyThreadState_Clear()` may
call back into `PyGILState_Ensure()` and `PyGILState_Release()`. If
`gilstate_counter` is zero, it will try to create a new thread state before
the current active thread state is destroyed, leading to an assertion failure
or crash.
This commit is contained in:
Sam Gross 2024-05-31 10:50:52 -04:00 committed by GitHub
parent 891c1e36f4
commit bcc1be39cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 36 additions and 0 deletions

View file

@ -2888,6 +2888,22 @@ class TestThreadState(unittest.TestCase):
t.start()
t.join()
@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_thread_gilstate_in_clear(self):
# See https://github.com/python/cpython/issues/119585
class C:
def __del__(self):
_testcapi.gilstate_ensure_release()
# Thread-local variables are destroyed in `PyThreadState_Clear()`.
local_var = threading.local()
def callback():
local_var.x = C()
_testcapi._test_thread_state(callback)
@threading_helper.reap_threads
@threading_helper.requires_working_threading()
def test_gilstate_ensure_no_deadlock(self):