Skip to content

Commit c8a47e7

Browse files
authored
bpo-23325: Fix SIG_IGN and SIG_DFL int comparison in signal module (GH-31759)
1 parent 5498a61 commit c8a47e7

File tree

2 files changed

+25
-13
lines changed

2 files changed

+25
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The :mod:`signal` module no longer assumes that :const:`~signal.SIG_IGN` and
2+
:const:`~signal.SIG_DFL` are small int singletons.

Modules/signalmodule.c

+23-13
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,17 @@ get_signal_state(PyObject *module)
177177
}
178178

179179

180+
static inline int
181+
compare_handler(PyObject *func, PyObject *dfl_ign_handler)
182+
{
183+
assert(PyLong_CheckExact(dfl_ign_handler));
184+
if (!PyLong_CheckExact(func)) {
185+
return 0;
186+
}
187+
// Assume that comparison of two PyLong objects will never fail.
188+
return PyObject_RichCompareBool(func, dfl_ign_handler, Py_EQ) == 1;
189+
}
190+
180191
#ifdef HAVE_GETITIMER
181192
/* auxiliary functions for setitimer */
182193
static int
@@ -528,21 +539,18 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
528539
"signal number out of range");
529540
return NULL;
530541
}
531-
if (handler == modstate->ignore_handler) {
542+
if (PyCallable_Check(handler)) {
543+
func = signal_handler;
544+
} else if (compare_handler(handler, modstate->ignore_handler)) {
532545
func = SIG_IGN;
533-
}
534-
else if (handler == modstate->default_handler) {
546+
} else if (compare_handler(handler, modstate->default_handler)) {
535547
func = SIG_DFL;
536-
}
537-
else if (!PyCallable_Check(handler)) {
548+
} else {
538549
_PyErr_SetString(tstate, PyExc_TypeError,
539550
"signal handler must be signal.SIG_IGN, "
540551
"signal.SIG_DFL, or a callable object");
541552
return NULL;
542553
}
543-
else {
544-
func = signal_handler;
545-
}
546554

547555
/* Check for pending signals before changing signal handler */
548556
if (_PyErr_CheckSignalsTstate(tstate)) {
@@ -1752,8 +1760,8 @@ _PySignal_Fini(void)
17521760
set_handler(signum, NULL);
17531761
if (func != NULL
17541762
&& func != Py_None
1755-
&& func != state->default_handler
1756-
&& func != state->ignore_handler)
1763+
&& !compare_handler(func, state->default_handler)
1764+
&& !compare_handler(func, state->ignore_handler))
17571765
{
17581766
PyOS_setsig(signum, SIG_DFL);
17591767
}
@@ -1824,8 +1832,9 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
18241832
* (see bpo-43406).
18251833
*/
18261834
PyObject *func = get_handler(i);
1827-
if (func == NULL || func == Py_None || func == state->ignore_handler ||
1828-
func == state->default_handler) {
1835+
if (func == NULL || func == Py_None ||
1836+
compare_handler(func, state->ignore_handler) ||
1837+
compare_handler(func, state->default_handler)) {
18291838
/* No Python signal handler due to aforementioned race condition.
18301839
* We can't call raise() as it would break the assumption
18311840
* that PyErr_SetInterrupt() only *simulates* an incoming
@@ -1893,7 +1902,8 @@ PyErr_SetInterruptEx(int signum)
18931902

18941903
signal_state_t *state = &signal_global_state;
18951904
PyObject *func = get_handler(signum);
1896-
if (func != state->ignore_handler && func != state->default_handler) {
1905+
if (!compare_handler(func, state->ignore_handler)
1906+
&& !compare_handler(func, state->default_handler)) {
18971907
trip_signal(signum);
18981908
}
18991909
return 0;

0 commit comments

Comments
 (0)