From f9e6b8d86c4d9c9f0109089c7116f4e4c9cca042 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 24 Jan 2023 12:30:51 -0700 Subject: [PATCH 1/3] Swap the "auto TSS" tstate too. --- Python/pystate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Python/pystate.c b/Python/pystate.c index 8bb49d954a81b6..275fe8217e8653 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1750,6 +1750,9 @@ _PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts) if (check && check->interp == newts->interp) { Py_FatalError("Invalid thread state for this thread"); } + // Make sure the "autoTSS" thread state matches the current one. + // XXX Call bind_gilstate_tstate() instead? + giltstate_tss_set(runtime, newts); } } errno = err; From 3e8c3efcd85f7d22a5e3fc191d1d1c12d25feda7 Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Wed, 25 Jan 2023 11:17:51 -0700 Subject: [PATCH 2/3] Do not bail out in bind_gilstate_tstate() if it's already set. --- Python/pystate.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/Python/pystate.c b/Python/pystate.c index 275fe8217e8653..ed8c2e212a5539 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -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 @@ -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); @@ -1738,23 +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"); - } - // Make sure the "autoTSS" thread state matches the current one. - // XXX Call bind_gilstate_tstate() instead? - giltstate_tss_set(runtime, newts); - } - } errno = err; #endif return oldts; From 631c872c0bd66aeeac5c99fa90999d9a9a92fadd Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Mon, 30 Jan 2023 11:56:19 -0700 Subject: [PATCH 3/3] Add a NEWS entry. --- .../2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst b/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst new file mode 100644 index 00000000000000..b3c1896b9493e1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-01-30-11-56-09.gh-issue-59956.7xqnC_.rst @@ -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.