summaryrefslogtreecommitdiffstats
path: root/Python/pystate.c
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-05-31 15:42:09 (GMT)
committerGitHub <noreply@github.com>2024-05-31 15:42:09 (GMT)
commit738cf216093e844c154f9ba36605f485fac5ff0d (patch)
tree0d8c7c81918c7e62cf540bd0d8e5a7fff5e2ef1c /Python/pystate.c
parentd4680b9e17815140b512a399069400794dae1f97 (diff)
downloadcpython-738cf216093e844c154f9ba36605f485fac5ff0d.zip
cpython-738cf216093e844c154f9ba36605f485fac5ff0d.tar.gz
cpython-738cf216093e844c154f9ba36605f485fac5ff0d.tar.bz2
[3.12] gh-119585: Fix crash involving `PyGILState_Release()` and `PyThreadState_Clear()` (GH-119753) (#119861)
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. (cherry picked from commit bcc1be39cb1d04ad9fc0bd1b9193d3972835a57c)
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 1337516..d0651fb 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2277,12 +2277,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(runtime) == tstate);
_PyThreadState_DeleteCurrent(tstate);
}