https://github.com/python/cpython/commit/4aab0c4ea2c569fce374a05cdd3b91009944f82b
commit: 4aab0c4ea2c569fce374a05cdd3b91009944f82b
branch: main
author: Pieter Eendebak <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-10-31T17:39:25+05:30
summary:
gh-157746: Make PyErr_CheckSignals() cheap when no signal is pending (#157748)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-09-25-11-05-00.gh-issue-157746.q7Lk3d.rst
M Modules/signalmodule.c
M Python/ceval_gil.c
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-09-25-11-05-00.gh-issue-157746.q7Lk3d.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-25-11-05-00.gh-issue-157746.q7Lk3d.rst
new file mode 100644
index 000000000000000..eb9e95defa3d6c2
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-09-25-11-05-00.gh-issue-157746.q7Lk3d.rst
@@ -0,0 +1,3 @@
+Reduce the overhead of :c:func:`PyErr_CheckSignals` when no signal is
+pending: the cheap flag checks are now done before the main-thread check and
+the remote debugger configuration lookup.
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index bc5aef55648e071..addf6b456b1f95c 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -1796,25 +1796,18 @@ PyErr_CheckSignals(void)
_PyRunRemoteDebugger(tstate);
#endif
- if (_Py_ThreadCanHandleSignals(tstate->interp)) {
- if (_PyErr_CheckSignalsTstate(tstate) < 0) {
- return -1;
- }
+ if (_PyErr_CheckSignalsTstate(tstate) < 0) {
+ return -1;
}
return 0;
}
-/* Declared in cpython/pyerrors.h */
-int
-_PyErr_CheckSignalsTstate(PyThreadState *tstate)
+// Out of line, to keep the common case of _PyErr_CheckSignalsTstate() cheap.
+Py_NO_INLINE static int
+run_tripped_handlers(PyThreadState *tstate)
{
- _Py_CHECK_EMSCRIPTEN_SIGNALS();
- if (!_Py_atomic_load_int(&is_tripped)) {
- return 0;
- }
-
/*
* The is_tripped variable is meant to speed up the calls to
* PyErr_CheckSignals (both directly or via pending calls) when no
@@ -1895,6 +1888,20 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
}
+/* Declared in pycore_pyerrors.h */
+int
+_PyErr_CheckSignalsTstate(PyThreadState *tstate)
+{
+ _Py_CHECK_EMSCRIPTEN_SIGNALS();
+ if (!_Py_atomic_load_int(&is_tripped)) {
+ return 0;
+ }
+ if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
+ return 0;
+ }
+ return run_tripped_handlers(tstate);
+}
+
int
_PyErr_CheckSignals(void)
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index 49b2ede4ed3e60f..91c75cdd2ed4133 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -830,9 +830,6 @@ handle_signals(PyThreadState *tstate)
{
assert(_PyThreadState_CheckConsistency(tstate));
_Py_unset_eval_breaker_bit(tstate, _PY_SIGNALS_PENDING_BIT);
- if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
- return 0;
- }
if (_PyErr_CheckSignalsTstate(tstate) < 0) {
/* On failure, re-schedule a call to handle_signals(). */
_Py_set_eval_breaker_bit(tstate, _PY_SIGNALS_PENDING_BIT);
@@ -1258,10 +1255,11 @@ static inline void run_remote_debugger_script(PyObject
*path)
int _PyRunRemoteDebugger(PyThreadState *tstate)
{
+ if (tstate->remote_debugger_support.debugger_pending_call != 1) {
+ return 0;
+ }
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
- if (config->remote_debug == 1
- && tstate->remote_debugger_support.debugger_pending_call == 1)
- {
+ if (config->remote_debug == 1) {
tstate->remote_debugger_support.debugger_pending_call = 0;
// Immediately make a copy in case of a race with another debugger
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]