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.
This commit is contained in:
Victor Stinner 2020-11-17 18:15:20 +01:00 committed by GitHub
parent a1f401a58b
commit 0ae323b87f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 53 deletions

View file

@ -0,0 +1,4 @@
On Windows, the ``SIGINT`` event, ``_PyOS_SigintEvent()``, is now created
even if Python is configured to not install signal handlers (if
:c:member:`PyConfig.install_signal_handlers` equals to 0, or
``Py_InitializeEx(0)``).

View file

@ -130,15 +130,16 @@ static _Py_atomic_int is_tripped;
static PyObject *DefaultHandler; static PyObject *DefaultHandler;
static PyObject *IgnoreHandler; static PyObject *IgnoreHandler;
static PyObject *IntHandler;
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
static HANDLE sigint_event = NULL; static HANDLE sigint_event = NULL;
#endif #endif
#ifdef HAVE_GETITIMER #if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
static PyObject *ItimerError; static PyObject *ItimerError;
#endif
#ifdef HAVE_GETITIMER
/* auxiliary functions for setitimer */ /* auxiliary functions for setitimer */
static int static int
timeval_from_double(PyObject *obj, struct timeval *tv) timeval_from_double(PyObject *obj, struct timeval *tv)
@ -1074,7 +1075,6 @@ signal_valid_signals_impl(PyObject *module)
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
static int initialized;
static PyStructSequence_Field struct_siginfo_fields[] = { static PyStructSequence_Field struct_siginfo_fields[] = {
{"si_signo", "signal number"}, {"si_signo", "signal number"},
{"si_code", "signal code"}, {"si_code", "signal code"},
@ -1384,30 +1384,19 @@ signal_exec(PyObject *m)
{ {
/* add the functions */ /* add the functions */
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
if (!initialized) {
if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) {
return -1;
}
}
if (PyModule_AddType(m, &SiginfoType) < 0) { if (PyModule_AddType(m, &SiginfoType) < 0) {
return -1; return -1;
} }
initialized = 1;
#endif #endif
/* Add some symbolic constants to the module */ /* Add some symbolic constants to the module */
PyObject *d = PyModule_GetDict(m); PyObject *d = PyModule_GetDict(m);
DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL); if (PyDict_SetItemString(d, "SIG_DFL", DefaultHandler) < 0) {
if (!DefaultHandler ||
PyDict_SetItemString(d, "SIG_DFL", DefaultHandler) < 0) {
return -1; return -1;
} }
IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN); if (PyDict_SetItemString(d, "SIG_IGN", IgnoreHandler) < 0) {
if (!IgnoreHandler ||
PyDict_SetItemString(d, "SIG_IGN", IgnoreHandler) < 0) {
return -1; return -1;
} }
@ -1427,15 +1416,9 @@ signal_exec(PyObject *m)
return -1; return -1;
#endif #endif
IntHandler = PyMapping_GetItemString(d, "default_int_handler");
if (!IntHandler)
return -1;
_Py_atomic_store_relaxed(&Handlers[0].tripped, 0);
for (int i = 1; i < NSIG; i++) { for (int i = 1; i < NSIG; i++) {
void (*t)(int); void (*t)(int);
t = PyOS_getsig(i); t = PyOS_getsig(i);
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
if (t == SIG_DFL) if (t == SIG_DFL)
Handlers[i].func = DefaultHandler; Handlers[i].func = DefaultHandler;
else if (t == SIG_IGN) else if (t == SIG_IGN)
@ -1445,9 +1428,13 @@ signal_exec(PyObject *m)
Py_INCREF(Handlers[i].func); Py_INCREF(Handlers[i].func);
} }
if (Handlers[SIGINT].func == DefaultHandler) { if (Handlers[SIGINT].func == DefaultHandler) {
PyObject *int_handler = PyMapping_GetItemString(d, "default_int_handler");
if (!int_handler) {
return -1;
}
/* Install default int handler */ /* Install default int handler */
Py_INCREF(IntHandler); Py_SETREF(Handlers[SIGINT].func, int_handler);
Py_SETREF(Handlers[SIGINT].func, IntHandler);
PyOS_setsig(SIGINT, signal_handler); PyOS_setsig(SIGINT, signal_handler);
} }
@ -1617,11 +1604,8 @@ signal_exec(PyObject *m)
return -1; return -1;
#endif #endif
#if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER) #if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
ItimerError = PyErr_NewException("signal.ItimerError", if (PyDict_SetItemString(d, "ItimerError", ItimerError) < 0) {
PyExc_OSError, NULL);
if (!ItimerError ||
PyDict_SetItemString(d, "ItimerError", ItimerError) < 0) {
return -1; return -1;
} }
#endif #endif
@ -1636,11 +1620,6 @@ signal_exec(PyObject *m)
return -1; return -1;
#endif #endif
#ifdef MS_WINDOWS
/* Create manual-reset event, initially unset */
sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE);
#endif
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
return -1; return -1;
} }
@ -1677,23 +1656,31 @@ PyInit__signal(void)
void void
_PySignal_Fini(void) _PySignal_Fini(void)
{ {
int i; // Restore default signals and clear handlers
PyObject *func; for (int signum = 1; signum < NSIG; signum++) {
PyObject *func = Handlers[signum].func;
for (i = 1; i < NSIG; i++) { _Py_atomic_store_relaxed(&Handlers[signum].tripped, 0);
func = Handlers[i].func; Handlers[signum].func = NULL;
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0); if (func != NULL
Handlers[i].func = NULL; && func != Py_None
if (func != NULL && func != Py_None && && func != DefaultHandler
func != DefaultHandler && func != IgnoreHandler) && func != IgnoreHandler)
PyOS_setsig(i, SIG_DFL); {
PyOS_setsig(signum, SIG_DFL);
}
Py_XDECREF(func); Py_XDECREF(func);
} }
Py_CLEAR(IntHandler); #ifdef MS_WINDOWS
if (sigint_event != NULL) {
CloseHandle(sigint_event);
sigint_event = NULL;
}
#endif
Py_CLEAR(DefaultHandler); Py_CLEAR(DefaultHandler);
Py_CLEAR(IgnoreHandler); Py_CLEAR(IgnoreHandler);
#ifdef HAVE_GETITIMER #if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
Py_CLEAR(ItimerError); Py_CLEAR(ItimerError);
#endif #endif
} }
@ -1792,14 +1779,9 @@ PyErr_SetInterrupt(void)
} }
} }
int static int
_PySignal_Init(int install_signal_handlers) signal_install_handlers(void)
{ {
if (!install_signal_handlers) {
// Nothing to do
return 0;
}
#ifdef SIGPIPE #ifdef SIGPIPE
PyOS_setsig(SIGPIPE, SIG_IGN); PyOS_setsig(SIGPIPE, SIG_IGN);
#endif #endif
@ -1821,6 +1803,58 @@ _PySignal_Init(int install_signal_handlers)
} }
int
_PySignal_Init(int install_signal_handlers)
{
DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL);
if (!DefaultHandler) {
return -1;
}
IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN);
if (!IgnoreHandler) {
return -1;
}
#if defined(HAVE_GETITIMER) || defined(HAVE_SETITIMER)
ItimerError = PyErr_NewException("signal.ItimerError",
PyExc_OSError, NULL);
if (!ItimerError) {
return -1;
}
#endif
#ifdef MS_WINDOWS
/* Create manual-reset event, initially unset */
sigint_event = CreateEvent(NULL, TRUE, FALSE, FALSE);
if (sigint_event == NULL) {
PyErr_SetFromWindowsErr(0);
return -1;
}
#endif
#if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT)
if (SiginfoType.tp_name == NULL) {
if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) {
return -1;
}
}
#endif
for (int signum = 1; signum < NSIG; signum++) {
_Py_atomic_store_relaxed(&Handlers[signum].tripped, 0);
}
if (install_signal_handlers) {
if (signal_install_handlers() < 0) {
return -1;
}
}
return 0;
}
// The caller doesn't have to hold the GIL // The caller doesn't have to hold the GIL
int int
_PyOS_InterruptOccurred(PyThreadState *tstate) _PyOS_InterruptOccurred(PyThreadState *tstate)