8000 gh-59956: Partial Fix for GILState API Compatibility with Subinterpre… · python/cpython@132b3f8 · GitHub
[go: up one dir, main page]

Skip to content
  • Commit 132b3f8

    Browse files
    gh-59956: Partial Fix for GILState API Compatibility with Subinterpreters (gh-101431)
    The GILState API (PEP 311) implementation from 2003 made the assumption that only one thread state would ever be used for any given OS thread, explicitly disregarding the case of subinterpreters. However, PyThreadState_Swap() still facilitated switching between subinterpreters, meaning the "current" thread state (holding the GIL), and the GILState thread state could end up out of sync, causing problems (including crashes). This change addresses the issue by keeping the two in sync in PyThreadState_Swap(). I verified the fix against gh-99040. Note that the other GILState-subinterpreter incompatibility (with autoInterpreterState) is not resolved here. #59956
    1 parent 262003f commit 132b3f8

    File tree

    2 files changed

    +7
    -21
    lines changed

    2 files changed

    +7
    -21
    lines changed
    Lines changed: 3 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1,3 @@
    1+
    The GILState API is now partially compatible with subinterpreters.
    2+
    Previously, ``PyThreadState_GET()`` and ``PyGILState_GetThisThreadState()``
    3+
    would get out of sync, causing inconsistent behavior and crashes.

    Python/pystate.c

    Lines changed: 4 additions & 21 deletions
    Original file line numberDiff line numberDiff line change
    @@ -266,10 +266,10 @@ unbind_tstate(PyThreadState *tstate)
    266266
    thread state for an OS level thread is when there are multiple
    267267
    interpreters.
    268268
    269-
    The PyGILState_*() APIs don't work with multiple
    270-
    interpreters (see bpo-10915 and bpo-15751), so this function
    271-
    sets TSS only once. Thus, the first thread state created for that
    272-
    given OS level thread will "win", which seems reasonable behaviour.
    269+
    Before 3.12, the PyGILState_*() APIs didn't work with multiple
    270+
    interpreters (see bpo-10915 and bpo-15751), so this function used
    271+
    to set TSS only once. Thus, the first thread state created for that
    272+
    given OS level thread would "win", which seemed reasonable behaviour.
    273273
    */
    274274

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

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

    1741-
    /* It should not be possible for more than one thread state
    1742-
    to be used for a thread. Check this the best we can in debug
    1743-
    builds.
    1744-
    */
    1745-
    // XXX The above isn't true when multiple interpreters are involved.
    17461737
    #if defined(Py_DEBUG)
    1747-
    if (newts && gilstate_tss_initialized(runtime)) {
    1748-
    PyThreadState *check = gilstate_tss_get(runtime);
    1749-
    if (check != newts) {
    1750-
    if (check && check->interp == newts->interp) {
    1751-
    Py_FatalError("Invalid thread state for this thread");
    1752-
    }
    1753-
    }
    1754-
    }
    17551738
    errno = err;
    17561739
    #endif
    17571740
    return oldts;

    0 commit comments

    Comments
     (0)
    0