summaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c18
-rw-r--r--Python/ceval_gil.h9
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);