Skip to content

gh-59956: Partial Fix for GILState API Compatibility with Subinterpreters #101431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The GILState API is now partially compatible with subinterpreters.
Previously, ``PyThreadState_GET()`` and ``PyGILState_GetThisThreadState()``
would get out of sync, causing inconsistent behavior and crashes.
25 changes: 4 additions & 21 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,10 @@ unbind_tstate(PyThreadState *tstate)
thread state for an OS level thread is when there are multiple
interpreters.

The PyGILState_*() APIs don't work with multiple
interpreters (see bpo-10915 and bpo-15751), so this function
sets TSS only once. Thus, the first thread state created for that
given OS level thread will "win", which seems reasonable behaviour.
Before 3.12, the PyGILState_*() APIs didn't work with multiple
interpreters (see bpo-10915 and bpo-15751), so this function used
to set TSS only once. Thus, the first thread state created for that
given OS level thread would "win", which seemed reasonable behaviour.
*/

static void
Expand All @@ -286,10 +286,6 @@ bind_gilstate_tstate(PyThreadState *tstate)
assert(tstate != tcur);

if (tcur != NULL) {
// The original gilstate implementation only respects the
// first thread state set.
// XXX Skipping like this does not play nice with multiple interpreters.
return;
tcur->_status.bound_gilstate = 0;
}
gilstate_tss_set(runtime, tstate);
Expand Down Expand Up @@ -1738,20 +1734,7 @@ _PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)
tstate_activate(newts);
}

/* It should not be possible for more than one thread state
to be used for a thread. Check this the best we can in debug
builds.
*/
// XXX The above isn't true when multiple interpreters are involved.
#if defined(Py_DEBUG)
if (newts && gilstate_tss_initialized(runtime)) {
PyThreadState *check = gilstate_tss_get(runtime);
if (check != newts) {
if (check && check->interp == newts->interp) {
Py_FatalError("Invalid thread state for this thread");
}
}
}
errno = err;
#endif
return oldts;
Expand Down