Skip to content

Commit 4aab0c4

Browse files
authored
gh-157746: Make PyErr_CheckSignals() cheap when no signal is pending (#157748)
1 parent 07db3e9 commit 4aab0c4

3 files changed

Lines changed: 26 additions & 18 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Reduce the overhead of :c:func:`PyErr_CheckSignals` when no signal is
2+
pending: the cheap flag checks are now done before the main-thread check and
3+
the remote debugger configuration lookup.

‎Modules/signalmodule.c‎

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,25 +1796,18 @@ PyErr_CheckSignals(void)
17961796
_PyRunRemoteDebugger(tstate);
17971797
#endif
17981798

1799-
if (_Py_ThreadCanHandleSignals(tstate->interp)) {
1800-
if (_PyErr_CheckSignalsTstate(tstate) < 0) {
1801-
return -1;
1802-
}
1799+
if (_PyErr_CheckSignalsTstate(tstate) < 0) {
1800+
return -1;
18031801
}
18041802

18051803
return 0;
18061804
}
18071805

18081806

1809-
/* Declared in cpython/pyerrors.h */
1810-
int
1811-
_PyErr_CheckSignalsTstate(PyThreadState *tstate)
1807+
// Out of line, to keep the common case of _PyErr_CheckSignalsTstate() cheap.
1808+
Py_NO_INLINE static int
1809+
run_tripped_handlers(PyThreadState *tstate)
18121810
{
1813-
_Py_CHECK_EMSCRIPTEN_SIGNALS();
1814-
if (!_Py_atomic_load_int(&is_tripped)) {
1815-
return 0;
1816-
}
1817-
18181811
/*
18191812
* The is_tripped variable is meant to speed up the calls to
18201813
* PyErr_CheckSignals (both directly or via pending calls) when no
@@ -1895,6 +1888,20 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
18951888
}
18961889

18971890

1891+
/* Declared in pycore_pyerrors.h */
1892+
int
1893+
_PyErr_CheckSignalsTstate(PyThreadState *tstate)
1894+
{
1895+
_Py_CHECK_EMSCRIPTEN_SIGNALS();
1896+
if (!_Py_atomic_load_int(&is_tripped)) {
1897+
return 0;
1898+
}
1899+
if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
1900+
return 0;
1901+
}
1902+
return run_tripped_handlers(tstate);
1903+
}
1904+
18981905

18991906
int
19001907
_PyErr_CheckSignals(void)

‎Python/ceval_gil.c‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -830,9 +830,6 @@ handle_signals(PyThreadState *tstate)
830830
{
831831
assert(_PyThreadState_CheckConsistency(tstate));
832832
_Py_unset_eval_breaker_bit(tstate, _PY_SIGNALS_PENDING_BIT);
833-
if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
834-
return 0;
835-
}
836833
if (_PyErr_CheckSignalsTstate(tstate) < 0) {
837834
/* On failure, re-schedule a call to handle_signals(). */
838835
_Py_set_eval_breaker_bit(tstate, _PY_SIGNALS_PENDING_BIT);
@@ -1258,10 +1255,11 @@ static inline void run_remote_debugger_script(PyObject *path)
12581255

12591256
int _PyRunRemoteDebugger(PyThreadState *tstate)
12601257
{
1258+
if (tstate->remote_debugger_support.debugger_pending_call != 1) {
1259+
return 0;
1260+
}
12611261
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
1262-
if (config->remote_debug == 1
1263-
&& tstate->remote_debugger_support.debugger_pending_call == 1)
1264-
{
1262+
if (config->remote_debug == 1) {
12651263
tstate->remote_debugger_support.debugger_pending_call = 0;
12661264

12671265
// Immediately make a copy in case of a race with another debugger

0 commit comments

Comments
 (0)