bpo-40010: COMPUTE_EVAL_BREAKER() checks for subinterpreter (GH-19087)

COMPUTE_EVAL_BREAKER() now also checks if the Python thread state
belongs to the main interpreter. Don't break the evaluation loop if
there are pending signals but the Python thread state it belongs to a
subinterpeter.

* Add _Py_IsMainThread() function.
* Add _Py_ThreadCanHandleSignals() function.
This commit is contained in:
Victor Stinner 2020-03-20 13:38:58 +01:00 committed by GitHub
parent da2914db4b
commit d2a8e5b42c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 53 deletions

View file

@ -136,14 +136,6 @@ is_tstate_valid(PyThreadState *tstate)
#endif
/* Only handle signals on the main thread of the main interpreter. */
static int
thread_can_handle_signals(void)
{
return (PyThread_get_thread_ident() == _PyRuntime.main_thread);
}
/* This can set eval_breaker to 0 even though gil_drop_request became
1. We believe this is all right because the eval loop will release
the GIL eventually anyway. */
@ -156,7 +148,7 @@ COMPUTE_EVAL_BREAKER(PyThreadState *tstate,
_Py_atomic_store_relaxed(&ceval2->eval_breaker,
_Py_atomic_load_relaxed(&ceval->gil_drop_request)
| (_Py_atomic_load_relaxed(&ceval->signals_pending)
&& thread_can_handle_signals())
&& _Py_ThreadCanHandleSignals(tstate))
| _Py_atomic_load_relaxed(&ceval2->pending.calls_to_do)
| ceval2->pending.async_exc);
}
@ -598,17 +590,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
static int
handle_signals(PyThreadState *tstate)
{
_PyRuntimeState *runtime = tstate->interp->runtime;
if (!thread_can_handle_signals()) {
return 0;
}
/*
* Ensure that the thread isn't currently running some other
* interpreter.
*/
PyInterpreterState *interp = tstate->interp;
if (interp != runtime->interpreters.main) {
if (!_Py_ThreadCanHandleSignals(tstate)) {
return 0;
}
@ -624,11 +606,8 @@ handle_signals(PyThreadState *tstate)
static int
make_pending_calls(PyThreadState *tstate)
{
_PyRuntimeState *runtime = tstate->interp->runtime;
/* only service pending calls on main thread */
if (PyThread_get_thread_ident() != runtime->main_thread) {
if (!_Py_IsMainThread()) {
return 0;
}

View file

@ -169,12 +169,6 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
#define HEAD_UNLOCK(runtime) \
PyThread_release_lock((runtime)->interpreters.mutex)
int
_Py_IsMainInterpreter(PyThreadState* tstate)
{
return (tstate->interp == tstate->interp->runtime->interpreters.main);
}
/* Forward declaration */
static void _PyGILState_NoteThreadState(
struct _gilstate_runtime_state *gilstate, PyThreadState* tstate);