Skip to content

Commit 0ae323b

Browse files
authored
bpo-41686: Always create the SIGINT event on Windows (GH-23344)
bpo-41686, bpo-41713: On Windows, the SIGINT event, _PyOS_SigintEvent(), is now created even if Python is configured to not install signal handlers (PyConfig.install_signal_handlers=0 or Py_InitializeEx(0)). Changes: * Move global variables initialization from signal_exec() to _PySignal_Init() to clarify that they are global variables cleared by _PySignal_Fini(). * _PySignal_Fini() now closes sigint_event. * IntHandler is no longer a global variable.
1 parent a1f401a commit 0ae323b

File tree

2 files changed

+91
-53
lines changed

2 files changed

+91
-53
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
On Windows, the ``SIGINT`` event, ``_PyOS_SigintEvent()``, is now created
2+
even if Python is configured to not install signal handlers (if
3+
:c:member:`PyConfig.install_signal_handlers` equals to 0, or
4+
``Py_InitializeEx(0)``).

Modules/signalmodule.c

Lines changed: 87 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,16 @@ static _Py_atomic_int is_tripped;
130130

131131
static PyObject *DefaultHandler;
132132
static PyObject *IgnoreHandler;
133-
static PyObject *IntHandler;
134133

135134
#ifdef MS_WINDOWS
136135
static HANDLE sigint_event = NULL;
137136
#endif
138137

139-
#ifdef HAVE_GETITIMER
138+
#if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
140139
static PyObject *ItimerError;
140+
#endif
141141

142+
#ifdef HAVE_GETITIMER
142143
/* auxiliary functions for setitimer */
143144
static int
144145
timeval_from_double(PyObject *obj, struct timeval *tv)
@@ -1074,7 +1075,6 @@ signal_valid_signals_impl(PyObject *module)
10741075

10751076

10761077
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
1077-
static int initialized;
10781078
static PyStructSequence_Field struct_siginfo_fields[] = {
10791079
{"si_signo", "signal number"},
10801080
{"si_code", "signal code"},
@@ -1384,30 +1384,19 @@ signal_exec(PyObject *m)
13841384
{
13851385
/* add the functions */
13861386
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
1387-
if (!initialized) {
1388-
if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) {
1389-
return -1;
1390-
}
1391-
}
1392-
13931387
if (PyModule_AddType(m, &SiginfoType) < 0) {
13941388
return -1;
13951389
}
1396-
initialized = 1;
13971390
#endif
13981391

13991392
/* Add some symbolic constants to the module */
14001393
PyObject *d = PyModule_GetDict(m);
14011394

1402-
DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL);
1403-
if (!DefaultHandler ||
1404-
PyDict_SetItemString(d, "SIG_DFL", DefaultHandler) < 0) {
1395+
if (PyDict_SetItemString(d, "SIG_DFL", DefaultHandler) < 0) {
14051396
return -1;
14061397
}
14071398

1408-
IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN);
1409-
if (!IgnoreHandler ||
1410-
PyDict_SetItemString(d, "SIG_IGN", IgnoreHandler) < 0) {
1399+
if (PyDict_SetItemString(d, "SIG_IGN", IgnoreHandler) < 0) {
14111400
return -1;
14121401
}
14131402

@@ -1427,15 +1416,9 @@ signal_exec(PyObject *m)
14271416
return -1;
14281417
#endif
14291418

1430-
IntHandler = PyMapping_GetItemString(d, "default_int_handler");
1431-
if (!IntHandler)
1432-
return -1;
1433-
1434-
_Py_atomic_store_relaxed(&Handlers[0].tripped, 0);
14351419
for (int i = 1; i < NSIG; i++) {
14361420
void (*t)(int);
14371421
t = PyOS_getsig(i);
1438-
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
14391422
if (t == SIG_DFL)
14401423
Handlers[i].func = DefaultHandler;
14411424
else if (t == SIG_IGN)
@@ -1445,9 +1428,13 @@ signal_exec(PyObject *m)
14451428
Py_INCREF(Handlers[i].func);
14461429
}
14471430
if (Handlers[SIGINT].func == DefaultHandler) {
1431+
PyObject *int_handler = PyMapping_GetItemString(d, "default_int_handler");
1432+
if (!int_handler) {
1433+
return -1;
1434+
}
1435+
14481436
/* Install default int handler */
1449-
Py_INCREF(IntHandler);
1450-
Py_SETREF(Handlers[SIGINT].func, IntHandler);
1437+
Py_SETREF(Handlers[SIGINT].func, int_handler);
14511438
PyOS_setsig(SIGINT, signal_handler);
14521439
}
14531440

@@ -1617,11 +1604,8 @@ signal_exec(PyObject *m)
16171604
return -1;
16181605
#endif
16191606

1620-
#if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER)
1621-
ItimerError = PyErr_NewException("signal.ItimerError",
1622-
PyExc_OSError, NULL);
1623-
if (!ItimerError ||
1624-
PyDict_SetItemString(d, "ItimerError", ItimerError) < 0) {
1607+
#if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
1608+
if (PyDict_SetItemString(d, "ItimerError", ItimerError) < 0) {
16251609
return -1;
16261610
}
16271611
#endif
@@ -1636,11 +1620,6 @@ signal_exec(PyObject *m)
16361620
return -1;
16371621
#endif
16381622

1639-
#ifdef MS_WINDOWS
1640-
/* Create manual-reset event, initially unset */
1641-
sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE);
1642-
#endif
1643-
16441623
if (PyErr_Occurred()) {
16451624
return -1;
16461625
}
@@ -1677,23 +1656,31 @@ PyInit__signal(void)
16771656
void
16781657
_PySignal_Fini(void)
16791658
{
1680-
int i;
1681-
PyObject *func;
1682-
1683-
for (i = 1; i < NSIG; i++) {
1684-
func = Handlers[i].func;
1685-
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
1686-
Handlers[i].func = NULL;
1687-
if (func != NULL && func != Py_None &&
1688-
func != DefaultHandler && func != IgnoreHandler)
1689-
PyOS_setsig(i, SIG_DFL);
1659+
// Restore default signals and clear handlers
1660+
for (int signum = 1; signum < NSIG; signum++) {
1661+
PyObject *func = Handlers[signum].func;
1662+
_Py_atomic_store_relaxed(&Handlers[signum].tripped, 0);
1663+
Handlers[signum].func = NULL;
1664+
if (func != NULL
1665+
&& func != Py_None
1666+
&& func != DefaultHandler
1667+
&& func != IgnoreHandler)
1668+
{
1669+
PyOS_setsig(signum, SIG_DFL);
1670+
}
16901671
Py_XDECREF(func);
16911672
}
16921673

1693-
Py_CLEAR(IntHandler);
1674+
#ifdef MS_WINDOWS
1675+
if (sigint_event != NULL) {
1676+
CloseHandle(sigint_event);
1677+
sigint_event = NULL;
1678+
}
1679+
#endif
1680+
16941681
Py_CLEAR(DefaultHandler);
16951682
Py_CLEAR(IgnoreHandler);
1696-
#ifdef HAVE_GETITIMER
1683+
#if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
16971684
Py_CLEAR(ItimerError);
16981685
#endif
16991686
}
@@ -1792,14 +1779,9 @@ PyErr_SetInterrupt(void)
17921779
}
17931780
}
17941781

1795-
int
1796-
_PySignal_Init(int install_signal_handlers)
1782+
static int
1783+
signal_install_handlers(void)
17971784
{
1798-
if (!install_signal_handlers) {
1799-
// Nothing to do
1800-
return 0;
1801-
}
1802-
18031785
#ifdef SIGPIPE
18041786
PyOS_setsig(SIGPIPE, SIG_IGN);
18051787
#endif
@@ -1821,6 +1803,58 @@ _PySignal_Init(int install_signal_handlers)
18211803
}
18221804

18231805

1806+
int
1807+
_PySignal_Init(int install_signal_handlers)
1808+
{
1809+
DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL);
1810+
if (!DefaultHandler) {
1811+
return -1;
1812+
}
1813+
1814+
IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN);
1815+
if (!IgnoreHandler) {
1816+
return -1;
1817+
}
1818+
1819+
#if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
1820+
ItimerError = PyErr_NewException("signal.ItimerError",
1821+
PyExc_OSError, NULL);
1822+
if (!ItimerError) {
1823+
return -1;
1824+
}
1825+
#endif
1826+
1827+
#ifdef MS_WINDOWS
1828+
/* Create manual-reset event, initially unset */
1829+
sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE);
1830+
if (sigint_event == NULL) {
1831+
PyErr_SetFromWindowsErr(0);
1832+
return -1;
1833+
}
1834+
#endif
1835+
1836+
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
1837+
if (SiginfoType.tp_name == NULL) {
1838+
if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) {
1839+
return -1;
1840+
}
1841+
}
1842+
#endif
1843+
1844+
for (int signum = 1; signum < NSIG; signum++) {
1845+
_Py_atomic_store_relaxed(&Handlers[signum].tripped, 0);
1846+
}
1847+
1848+
if (install_signal_handlers) {
1849+
if (signal_install_handlers() < 0) {
1850+
return -1;
1851+
}
1852+
}
1853+
1854+
return 0;
1855+
}
1856+
1857+
18241858
// The caller doesn't have to hold the GIL
18251859
int
18261860
_PyOS_InterruptOccurred(PyThreadState *tstate)

0 commit comments

Comments
 (0)