aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/pystate.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-07-28 14:39:08 -0600
committerGitHub <noreply@github.com>2023-07-28 14:39:08 -0600
commit8ba4df91ae60833723d8d3b9afeb2b642f7176d5 (patch)
treec9e659951582121e0f08d97ca075825c58ab65a5 /Python/pystate.c
parent55ed85e49c16b1dc5470a8a893869261f6356c99 (diff)
downloadcpython-8ba4df91ae60833723d8d3b9afeb2b642f7176d5.tar.gz
cpython-8ba4df91ae60833723d8d3b9afeb2b642f7176d5.zip
gh-105699: Use a _Py_hashtable_t for the PyModuleDef Cache (gh-106974)
This fixes a crasher due to a race condition, triggered infrequently when two isolated (own GIL) subinterpreters simultaneously initialize their sys or builtins modules. The crash happened due the combination of the "detached" thread state we were using and the "last holder" logic we use for the GIL. It turns out it's tricky to use the same thread state for different threads. Who could have guessed? We solve the problem by eliminating the one object we were still sharing between interpreters. We replace it with a low-level hashtable, using the "raw" allocator to avoid tying it to the main interpreter. We also remove the accommodations for "detached" thread states, which were a dubious idea to start with.
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c69
1 files changed, 0 insertions, 69 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 3ec131b6cba..a1864cc3249 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -1640,75 +1640,6 @@ _PyThreadState_DeleteExcept(PyThreadState *tstate)
}
-//-------------------------
-// "detached" thread states
-//-------------------------
-
-void
-_PyThreadState_InitDetached(PyThreadState *tstate, PyInterpreterState *interp)
-{
- _PyRuntimeState *runtime = interp->runtime;
-
- HEAD_LOCK(runtime);
- interp->threads.next_unique_id += 1;
- uint64_t id = interp->threads.next_unique_id;
- HEAD_UNLOCK(runtime);
-
- init_threadstate(tstate, interp, id);
- // We do not call add_threadstate().
-}
-
-void
-_PyThreadState_ClearDetached(PyThreadState *tstate)
-{
- assert(!tstate->_status.bound);
- assert(!tstate->_status.bound_gilstate);
- assert(tstate->datastack_chunk == NULL);
- assert(tstate->thread_id == 0);
- assert(tstate->native_thread_id == 0);
- assert(tstate->next == NULL);
- assert(tstate->prev == NULL);
-
- PyThreadState_Clear(tstate);
- clear_datastack(tstate);
-}
-
-void
-_PyThreadState_BindDetached(PyThreadState *tstate)
-{
- assert(!_Py_IsMainInterpreter(
- current_fast_get(tstate->interp->runtime)->interp));
- assert(_Py_IsMainInterpreter(tstate->interp));
- bind_tstate(tstate);
- /* Unlike _PyThreadState_Bind(), we do not modify gilstate TSS. */
-}
-
-void
-_PyThreadState_UnbindDetached(PyThreadState *tstate)
-{
- assert(!_Py_IsMainInterpreter(
- current_fast_get(tstate->interp->runtime)->interp));
- assert(_Py_IsMainInterpreter(tstate->interp));
- assert(tstate_is_alive(tstate));
- assert(!tstate->_status.active);
- assert(gilstate_tss_get(tstate->interp->runtime) != tstate);
-
- unbind_tstate(tstate);
-
- /* This thread state may be bound/unbound repeatedly,
- so we must erase evidence that it was ever bound (or unbound). */
- tstate->_status.bound = 0;
- tstate->_status.unbound = 0;
-
- /* We must fully unlink the thread state from any OS thread,
- to allow it to be bound more than once. */
- tstate->thread_id = 0;
-#ifdef PY_HAVE_THREAD_NATIVE_ID
- tstate->native_thread_id = 0;
-#endif
-}
-
-
//----------
// accessors
//----------