Skip to content

Commit fa961e9

Browse files
committed
Fix concurrent shutdown races in PyGILState_Ensure().
1 parent 61f70ae commit fa961e9

1 file changed

Lines changed: 12 additions & 14 deletions

File tree

Python/pystate.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2759,30 +2759,24 @@ PyGILState_Check(void)
27592759
PyGILState_STATE
27602760
PyGILState_Ensure(void)
27612761
{
2762-
_PyRuntimeState *runtime = &_PyRuntime;
2763-
27642762
/* Note that we do not auto-init Python here - apart from
27652763
potential races with 2 threads auto-initializing, pep-311
27662764
spells out other issues. Embedders are expected to have
27672765
called Py_Initialize(). */
27682766

2769-
/* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been
2770-
called by Py_Initialize()
2771-
2772-
TODO: This isn't thread-safe. There's no protection here against
2773-
concurrent finalization of the interpreter; it's simply a guard
2774-
for *after* the interpreter has finalized.
2775-
*/
2776-
if (!_PyEval_ThreadsInitialized() || runtime->gilstate.autoInterpreterState == NULL) {
2777-
PyThread_hang_thread();
2778-
}
2779-
27802767
PyThreadState *tcur = gilstate_get();
27812768
int has_gil;
2769+
PyInterpreterRef ref;
27822770
if (tcur == NULL) {
27832771
/* Create a new Python thread state for this thread */
27842772
// XXX Use PyInterpreterState_EnsureThreadState()?
2785-
tcur = new_threadstate(runtime->gilstate.autoInterpreterState,
2773+
if (PyInterpreterRef_Main(&ref) < 0) {
2774+
// The main interpreter has finished, so we don't have
2775+
// any intepreter to make a thread state for. Hang the
2776+
// thread to act as failure.
2777+
PyThread_hang_thread();
2778+
}
2779+
tcur = new_threadstate(PyInterpreterRef_AsInterpreter(ref),
27862780
_PyThreadState_WHENCE_GILSTATE);
27872781
if (tcur == NULL) {
27882782
Py_FatalError("Couldn't create thread-state for new thread");
@@ -2804,6 +2798,10 @@ PyGILState_Ensure(void)
28042798
PyEval_RestoreThread(tcur);
28052799
}
28062800

2801+
if (tcur == NULL) {
2802+
PyInterpreterRef_Close(ref);
2803+
}
2804+
28072805
/* Update our counter in the thread-state - no need for locks:
28082806
- tcur will remain valid as we hold the GIL.
28092807
- the counter is safe as we are the only thread "allowed"

0 commit comments

Comments
 (0)