diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 18 | ||||
-rw-r--r-- | Python/ceval_gil.h | 9 |
2 files changed, 23 insertions, 4 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index b183cdaa27..d9a3ee0fab 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -120,6 +120,15 @@ static size_t opcache_global_hits = 0; static size_t opcache_global_misses = 0; #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. */ @@ -127,7 +136,8 @@ static size_t opcache_global_misses = 0; _Py_atomic_store_relaxed( \ &(ceval2)->eval_breaker, \ _Py_atomic_load_relaxed(&(ceval)->gil_drop_request) | \ - _Py_atomic_load_relaxed(&(ceval)->signals_pending) | \ + (_Py_atomic_load_relaxed(&(ceval)->signals_pending) \ + && thread_can_handle_signals()) | \ _Py_atomic_load_relaxed(&(ceval2)->pending.calls_to_do) | \ (ceval2)->pending.async_exc) @@ -156,10 +166,11 @@ static size_t opcache_global_misses = 0; COMPUTE_EVAL_BREAKER(ceval, ceval2); \ } while (0) +/* eval_breaker is not set to 1 if thread_can_handle_signals() is false. */ #define SIGNAL_PENDING_SIGNALS(ceval, ceval2) \ do { \ _Py_atomic_store_relaxed(&(ceval)->signals_pending, 1); \ - _Py_atomic_store_relaxed(&(ceval2)->eval_breaker, 1); \ + COMPUTE_EVAL_BREAKER(ceval, ceval2); \ } while (0) #define UNSIGNAL_PENDING_SIGNALS(ceval, ceval2) \ @@ -540,8 +551,7 @@ handle_signals(PyThreadState *tstate) { _PyRuntimeState *runtime = tstate->interp->runtime; - /* Only handle signals on main thread */ - if (PyThread_get_thread_ident() != runtime->main_thread) { + if (!thread_can_handle_signals()) { return 0; } /* diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index b359e3c423..da2a1d6f47 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -280,9 +280,18 @@ _ready: COND_SIGNAL(gil->switch_cond); MUTEX_UNLOCK(gil->switch_mutex); #endif + if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) { RESET_GIL_DROP_REQUEST(ceval, ceval2); } + else { + /* bpo-40010: eval_breaker should be recomputed to be set to 1 if there + a pending signal: signal received by another thread which cannot + handle signals. + + Note: RESET_GIL_DROP_REQUEST() calls COMPUTE_EVAL_BREAKER(). */ + COMPUTE_EVAL_BREAKER(ceval, ceval2); + } int must_exit = tstate_must_exit(tstate); |