Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7281898

Browse files
authored
bpo-38644: Pass tstate explicitly in signalmodule.c (GH-19184)
PyOS_InterruptOccurred() now checks _Py_ThreadCanHandleSignals() before checking if SIGINT is tripped.
1 parent 08faf00 commit 7281898

File tree

3 files changed

+93
-65
lines changed

3 files changed

+93
-65
lines changed

Include/internal/pycore_pyerrors.h

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ PyAPI_FUNC(PyObject *) _PyErr_FormatFromCauseTstate(
6565
const char *format,
6666
...);
6767

68+
PyAPI_FUNC(int) _PyErr_CheckSignalsTstate(PyThreadState *tstate);
69+
6870
#ifdef __cplusplus
6971
}
7072
#endif

Modules/signalmodule.c

+89-63
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
#include "Python.h"
77
#include "pycore_atomic.h"
8+
#include "pycore_call.h"
89
#include "pycore_ceval.h"
10+
#include "pycore_pyerrors.h"
911
#include "pycore_pystate.h"
1012

1113
#ifndef MS_WINDOWS
@@ -189,13 +191,6 @@ itimer_retval(struct itimerval *iv)
189191
}
190192
#endif
191193

192-
static int
193-
thread_can_handle_signals(void)
194-
{
195-
PyThreadState *tstate = _PyThreadState_GET();
196-
return _Py_ThreadCanHandleSignals(tstate);
197-
}
198-
199194
static PyObject *
200195
signal_default_int_handler(PyObject *self, PyObject *args)
201196
{
@@ -480,43 +475,53 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
480475
}
481476
#endif
482477

483-
if (!thread_can_handle_signals()) {
484-
PyErr_SetString(PyExc_ValueError,
485-
"signal only works in main thread "
486-
"of the main interpreter");
478+
PyThreadState *tstate = _PyThreadState_GET();
479+
if (!_Py_ThreadCanHandleSignals(tstate)) {
480+
_PyErr_SetString(tstate, PyExc_ValueError,
481+
"signal only works in main thread "
482+
"of the main interpreter");
487483
return NULL;
488484
}
489485
if (signalnum < 1 || signalnum >= NSIG) {
490-
PyErr_SetString(PyExc_ValueError,
491-
"signal number out of range");
486+
_PyErr_SetString(tstate, PyExc_ValueError,
487+
"signal number out of range");
492488
return NULL;
493489
}
494-
if (handler == IgnoreHandler)
490+
if (handler == IgnoreHandler) {
495491
func = SIG_IGN;
496-
else if (handler == DefaultHandler)
492+
}
493+
else if (handler == DefaultHandler) {
497494
func = SIG_DFL;
495+
}
498496
else if (!PyCallable_Check(handler)) {
499-
PyErr_SetString(PyExc_TypeError,
500-
"signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object");
501-
return NULL;
497+
_PyErr_SetString(tstate, PyExc_TypeError,
498+
"signal handler must be signal.SIG_IGN, "
499+
"signal.SIG_DFL, or a callable object");
500+
return NULL;
502501
}
503-
else
502+
else {
504503
func = signal_handler;
504+
}
505+
505506
/* Check for pending signals before changing signal handler */
506-
if (_PyErr_CheckSignals()) {
507+
if (_PyErr_CheckSignalsTstate(tstate)) {
507508
return NULL;
508509
}
509510
if (PyOS_setsig(signalnum, func) == SIG_ERR) {
510511
PyErr_SetFromErrno(PyExc_OSError);
511512
return NULL;
512513
}
514+
513515
old_handler = Handlers[signalnum].func;
514516
Py_INCREF(handler);
515517
Handlers[signalnum].func = handler;
516-
if (old_handler != NULL)
518+
519+
if (old_handler != NULL) {
517520
return old_handler;
518-
else
521+
}
522+
else {
519523
Py_RETURN_NONE;
524+
}
520525
}
521526

522527

@@ -698,10 +703,11 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds)
698703
return NULL;
699704
#endif
700705

701-
if (!thread_can_handle_signals()) {
702-
PyErr_SetString(PyExc_ValueError,
703-
"set_wakeup_fd only works in main thread "
704-
"of the main interpreter");
706+
PyThreadState *tstate = _PyThreadState_GET();
707+
if (!_Py_ThreadCanHandleSignals(tstate)) {
708+
_PyErr_SetString(tstate, PyExc_ValueError,
709+
"set_wakeup_fd only works in main thread "
710+
"of the main interpreter");
705711
return NULL;
706712
}
707713

@@ -727,12 +733,13 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds)
727733

728734
fd = (int)sockfd;
729735
if ((SOCKET_T)fd != sockfd) {
730-
PyErr_SetString(PyExc_ValueError, "invalid fd");
736+
_PyErr_SetString(tstate, PyExc_ValueError, "invalid fd");
731737
return NULL;
732738
}
733739

734-
if (_Py_fstat(fd, &status) != 0)
740+
if (_Py_fstat(fd, &status) != 0) {
735741
return NULL;
742+
}
736743

737744
/* on Windows, a file cannot be set to non-blocking mode */
738745
}
@@ -764,9 +771,9 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds)
764771
if (blocking < 0)
765772
return NULL;
766773
if (blocking) {
767-
PyErr_Format(PyExc_ValueError,
768-
"the fd %i must be in non-blocking mode",
769-
fd);
774+
_PyErr_Format(tstate, PyExc_ValueError,
775+
"the fd %i must be in non-blocking mode",
776+
fd);
770777
return NULL;
771778
}
772779
}
@@ -1673,23 +1680,22 @@ finisignal(void)
16731680
int
16741681
PyErr_CheckSignals(void)
16751682
{
1676-
if (!thread_can_handle_signals()) {
1683+
PyThreadState *tstate = _PyThreadState_GET();
1684+
if (!_Py_ThreadCanHandleSignals(tstate)) {
16771685
return 0;
16781686
}
16791687

1680-
return _PyErr_CheckSignals();
1688+
return _PyErr_CheckSignalsTstate(tstate);
16811689
}
16821690

16831691

16841692
/* Declared in cpython/pyerrors.h */
16851693
int
1686-
_PyErr_CheckSignals(void)
1694+
_PyErr_CheckSignalsTstate(PyThreadState *tstate)
16871695
{
1688-
int i;
1689-
PyObject *f;
1690-
1691-
if (!_Py_atomic_load(&is_tripped))
1696+
if (!_Py_atomic_load(&is_tripped)) {
16921697
return 0;
1698+
}
16931699

16941700
/*
16951701
* The is_tripped variable is meant to speed up the calls to
@@ -1707,32 +1713,48 @@ _PyErr_CheckSignals(void)
17071713
*/
17081714
_Py_atomic_store(&is_tripped, 0);
17091715

1710-
if (!(f = (PyObject *)PyEval_GetFrame()))
1711-
f = Py_None;
1716+
PyObject *frame = (PyObject *)tstate->frame;
1717+
if (!frame) {
1718+
frame = Py_None;
1719+
}
17121720

1713-
for (i = 1; i < NSIG; i++) {
1714-
if (_Py_atomic_load_relaxed(&Handlers[i].tripped)) {
1715-
PyObject *result = NULL;
1716-
PyObject *arglist = Py_BuildValue("(iO)", i, f);
1717-
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
1718-
1719-
if (arglist) {
1720-
result = PyObject_Call(Handlers[i].func, arglist, NULL);
1721-
Py_DECREF(arglist);
1722-
}
1723-
if (!result) {
1724-
_Py_atomic_store(&is_tripped, 1);
1725-
return -1;
1726-
}
1721+
for (int i = 1; i < NSIG; i++) {
1722+
if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) {
1723+
continue;
1724+
}
1725+
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
17271726

1728-
Py_DECREF(result);
1727+
PyObject *arglist = Py_BuildValue("(iO)", i, frame);
1728+
PyObject *result;
1729+
if (arglist) {
1730+
result = _PyObject_Call(tstate, Handlers[i].func, arglist, NULL);
1731+
Py_DECREF(arglist);
1732+
}
1733+
else {
1734+
result = NULL;
1735+
}
1736+
if (!result) {
1737+
/* On error, re-schedule a call to _PyErr_CheckSignalsTstate() */
1738+
_Py_atomic_store(&is_tripped, 1);
1739+
return -1;
17291740
}
1741+
1742+
Py_DECREF(result);
17301743
}
17311744

17321745
return 0;
17331746
}
17341747

17351748

1749+
1750+
int
1751+
_PyErr_CheckSignals(void)
1752+
{
1753+
PyThreadState *tstate = _PyThreadState_GET();
1754+
return _PyErr_CheckSignalsTstate(tstate);
1755+
}
1756+
1757+
17361758
/* Simulate the effect of a signal.SIGINT signal arriving. The next time
17371759
PyErr_CheckSignals is called, the Python SIGINT signal handler will be
17381760
raised.
@@ -1765,14 +1787,17 @@ PyOS_FiniInterrupts(void)
17651787
int
17661788
PyOS_InterruptOccurred(void)
17671789
{
1768-
if (_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) {
1769-
if (!thread_can_handle_signals()) {
1770-
return 0;
1771-
}
1772-
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0);
1773-
return 1;
1790+
PyThreadState *tstate = _PyThreadState_GET();
1791+
if (!_Py_ThreadCanHandleSignals(tstate)) {
1792+
return 0;
17741793
}
1775-
return 0;
1794+
1795+
if (!_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) {
1796+
return 0;
1797+
}
1798+
1799+
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0);
1800+
return 1;
17761801
}
17771802

17781803
static void
@@ -1799,7 +1824,8 @@ _PySignal_AfterFork(void)
17991824
int
18001825
_PyOS_IsMainThread(void)
18011826
{
1802-
return thread_can_handle_signals();
1827+
PyThreadState *tstate = _PyThreadState_GET();
1828+
return _Py_ThreadCanHandleSignals(tstate);
18031829
}
18041830

18051831
#ifdef MS_WINDOWS

Python/ceval.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,8 @@ handle_signals(PyThreadState *tstate)
597597
}
598598

599599
UNSIGNAL_PENDING_SIGNALS(tstate);
600-
if (_PyErr_CheckSignals() < 0) {
601-
/* We're not done yet */
600+
if (_PyErr_CheckSignalsTstate(tstate) < 0) {
601+
/* On failure, re-schedule a call to handle_signals(). */
602602
SIGNAL_PENDING_SIGNALS(tstate);
603603
return -1;
604604
}

0 commit comments

Comments
 (0)