Skip to content

Commit d1b3d80

Browse files
committed
Hand off the GIL when waiting on interpreter references.
We should probably use an event instead of a silly loop like this, but I don't care at the moment.
1 parent c3d09d2 commit d1b3d80

File tree

2 files changed

+14
-0
lines changed

2 files changed

+14
-0
lines changed

Modules/_testcapimodule.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2763,6 +2763,15 @@ test_weak_interpreter_ref_after_shutdown(PyObject *self, PyObject *unused)
27632763
Py_RETURN_NONE;
27642764
}
27652765

2766+
static PyObject *
2767+
foo(PyObject *self, PyObject *foo)
2768+
{
2769+
PyInterpreterRef ref;
2770+
PyInterpreterRef_Get(&ref);
2771+
PyInterpreterRef_Close(ref);
2772+
Py_RETURN_NONE;
2773+
}
2774+
27662775
static PyMethodDef TestMethods[] = {
27672776
{"set_errno", set_errno, METH_VARARGS},
27682777
{"test_config", test_config, METH_NOARGS},
@@ -2861,6 +2870,7 @@ static PyMethodDef TestMethods[] = {
28612870
{"test_thread_state_ensure_nested", test_thread_state_ensure_nested, METH_NOARGS},
28622871
{"test_thread_state_ensure_crossinterp", test_thread_state_ensure_crossinterp, METH_NOARGS},
28632872
{"test_weak_interpreter_ref_after_shutdown", test_weak_interpreter_ref_after_shutdown, METH_NOARGS},
2873+
{"foo", foo, METH_NOARGS},
28642874
{NULL, NULL} /* sentinel */
28652875
};
28662876

Python/pylifecycle.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,6 +2127,7 @@ make_pre_finalization_calls(PyThreadState *tstate, int subinterpreters)
21272127
int has_subinterpreters = subinterpreters
21282128
? runtime_has_subinterpreters(interp->runtime)
21292129
: 0;
2130+
// TODO: The interpreter reference countdown probably isn't very efficient.
21302131
int should_continue = (interp_has_threads(interp)
21312132
|| interp_has_atexit_callbacks(interp)
21322133
|| interp_has_pending_calls(interp)
@@ -2135,9 +2136,12 @@ make_pre_finalization_calls(PyThreadState *tstate, int subinterpreters)
21352136
if (!should_continue) {
21362137
break;
21372138
}
2139+
// Temporarily let other threads execute
2140+
_PyThreadState_Detach(tstate);
21382141
_PyRWMutex_Unlock(&interp->references.lock);
21392142
_PyEval_StartTheWorldAll(interp->runtime);
21402143
PyMutex_Unlock(&interp->ceval.pending.mutex);
2144+
_PyThreadState_Attach(tstate);
21412145
}
21422146
assert(PyMutex_IsLocked(&interp->ceval.pending.mutex));
21432147
ASSERT_WORLD_STOPPED(interp);

0 commit comments

Comments
 (0)