diff options
author | Sam Gross <colesbury@gmail.com> | 2024-05-31 14:50:52 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-31 14:50:52 (GMT) |
commit | bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c (patch) | |
tree | 74444fcc18034b396ec249de8f9735441f4338da /Python/pystate.c | |
parent | 891c1e36f4e08da107443772a4eb50c72a83836d (diff) | |
download | cpython-bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c.zip cpython-bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c.tar.gz cpython-bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c.tar.bz2 |
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.
Diffstat (limited to 'Python/pystate.c')
-rw-r--r-- | Python/pystate.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/Python/pystate.c b/Python/pystate.c index 1ea1ad9..ad7e082 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2808,12 +2808,18 @@ PyGILState_Release(PyGILState_STATE oldstate) /* can't have been locked when we created it */ assert(oldstate == PyGILState_UNLOCKED); // XXX Unbind tstate here. + // gh-119585: `PyThreadState_Clear()` may call destructors that + // themselves use PyGILState_Ensure and PyGILState_Release, so make + // sure that gilstate_counter is not zero when calling it. + ++tstate->gilstate_counter; PyThreadState_Clear(tstate); + --tstate->gilstate_counter; /* Delete the thread-state. Note this releases the GIL too! * It's vital that the GIL be held here, to avoid shutdown * races; see bugs 225673 and 1061968 (that nasty bug has a * habit of coming back). */ + assert(tstate->gilstate_counter == 0); assert(current_fast_get() == tstate); _PyThreadState_DeleteCurrent(tstate); } |