8000 gh-100227: Make the Global Interned Dict Safe for Isolated Interpreters by ericsnowcurrently · Pull Request #102925 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-100227: Make the Global Interned Dict Safe for Isolated Interpreters #102925

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 1 commit
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
Prev Previous commit
Next Next commit
Add _Py_AcquireGlobalObjectsState() and _Py_ReleaseGlobalObjectsState().
  • Loading branch information
ericsnowcurrently committed Mar 22, 2023
commit 3b1bb8bd677630e3f905896bb84a5fa2e0cb616b
3 changes: 3 additions & 0 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ PyAPI_FUNC(void) _PyThreadState_DeleteExcept(PyThreadState *tstate);
extern void _PyThreadState_InitDetached(PyThreadState *, PyInterpreterState *);
extern void _PyThreadState_ClearDetached(PyThreadState *);

extern PyThreadState * _Py_AcquireGlobalObjectsState(PyInterpreterState *);
extern void _Py_ReleaseGlobalObjectsState(PyThreadState *);


static inline void
_PyThreadState_UpdateTracingState(PyThreadState *tstate)
Expand Down
75 changes: 75 additions & 0 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,81 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
#endif


//---------------
// global objects
//---------------

static PyThreadState *
bind_global_objects_state(_PyRuntimeState *runtime)
{
PyThreadState *main_tstate = &runtime->cached_objects.main_tstate;

bind_tstate(main_tstate);
/* Unlike _PyThreadState_Bind(), we do not modify gilstate TSS. */

return main_tstate;
}

static void
unbind_global_objects_state(_PyRuntimeState *runtime)
{
PyThreadState *main_tstate = &runtime->cached_objects.main_tstate;
assert(tstate_is_alive(main_tstate));
assert(!main_tstate->_status.active);
assert(gilstate_tss_get(runtime) != main_tstate);

unbind_tstate(main_tstate);

/* This thread state may be bound/unbound repeatedly,
so we must erase evidence that it was ever bound (or unbound). */
main_tstate->_status.bound = 0;
main_tstate->_status.unbound = 0;

/* We must fully unlink the thread state from any OS thread,
to allow it to be bound more than once. */
main_tstate->thread_id = 0;
#ifdef PY_HAVE_THREAD_NATIVE_ID
main_tstate->native_thread_id = 0;
#endif
}

PyThreadState *
_Py_AcquireGlobalObjectsState(PyInterpreterState *interp)
{
_PyRuntimeState *runtime = &_PyRuntime;
assert(interp != NULL);
assert(interp->runtime == runtime);

PyThreadState *oldts = NULL;
/* All global objects are owned by the main interpreter. */
if (!_Py_IsMainInterpreter(interp)) {
PyThreadState *main_tstate = bind_global_objects_state(runtime);

oldts = _PyThreadState_Swap(runtime, main_tstate);
assert(oldts != NULL);

unbind_global_objects_state(runtime);
}

return oldts;
}

void
_Py_ReleaseGlobalObjectsState(PyThreadState *oldts)
{
if (oldts != NULL) {
/* The thread state was swapped in _Py_AcquireGlobalObjectsState(),
because the main interpreter wasn't running in the OS thread.. */
_PyRuntimeState *runtime = &_PyRuntime;
assert(oldts->interp->runtime == runtime);
assert(!_Py_IsMainInterpreter(oldts->interp));

// The returned tstate should be _PyRuntime.cached_objects.main_tstate.
_PyThreadState_Swap(runtime, oldts);
}
}


/*************************************/
/* the per-interpreter runtime state */
/*************************************/
Expand Down
0