mirror of https://github.com/python/cpython
bpo-35724: Explicitly require the main interpreter for signal-handling. (GH-11530)
Ensure that the main interpreter is active (in the main thread) for signal-handling operations. This is increasingly relevant as people use subinterpreters more. https://bugs.python.org/issue35724
This commit is contained in:
parent
06babb2422
commit
64d6cc826d
|
@ -133,6 +133,7 @@ PyAPI_FUNC(PyObject *) _PyErr_TrySetFromCause(
|
|||
/* In signalmodule.c */
|
||||
|
||||
int PySignal_SetWakeupFd(int fd);
|
||||
PyAPI_FUNC(int) _PyErr_CheckSignals(void);
|
||||
|
||||
/* Support for adding program text to SyntaxErrors */
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Signal-handling is now guaranteed to happen relative to the main
|
||||
interpreter.
|
|
@ -99,6 +99,7 @@ class sigset_t_converter(CConverter):
|
|||
#include "pythread.h"
|
||||
static unsigned long main_thread;
|
||||
static pid_t main_pid;
|
||||
static PyInterpreterState *main_interp;
|
||||
|
||||
static volatile struct {
|
||||
_Py_atomic_int tripped;
|
||||
|
@ -185,6 +186,13 @@ itimer_retval(struct itimerval *iv)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
is_main(void)
|
||||
{
|
||||
return PyThread_get_thread_ident() == main_thread &&
|
||||
_PyInterpreterState_Get() == main_interp;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
signal_default_int_handler(PyObject *self, PyObject *args)
|
||||
{
|
||||
|
@ -464,7 +472,7 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
|
|||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (PyThread_get_thread_ident() != main_thread) {
|
||||
if (!is_main()) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"signal only works in main thread");
|
||||
return NULL;
|
||||
|
@ -486,7 +494,7 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
|
|||
else
|
||||
func = signal_handler;
|
||||
/* Check for pending signals before changing signal handler */
|
||||
if (PyErr_CheckSignals()) {
|
||||
if (_PyErr_CheckSignals()) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyOS_setsig(signalnum, func) == SIG_ERR) {
|
||||
|
@ -681,7 +689,7 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
return NULL;
|
||||
#endif
|
||||
|
||||
if (PyThread_get_thread_ident() != main_thread) {
|
||||
if (!is_main()) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"set_wakeup_fd only works in main thread");
|
||||
return NULL;
|
||||
|
@ -1314,6 +1322,7 @@ PyInit__signal(void)
|
|||
|
||||
main_thread = PyThread_get_thread_ident();
|
||||
main_pid = getpid();
|
||||
main_interp = _PyInterpreterState_Get();
|
||||
|
||||
/* Create the module and add the functions */
|
||||
m = PyModule_Create(&signalmodule);
|
||||
|
@ -1606,6 +1615,18 @@ finisignal(void)
|
|||
/* Declared in pyerrors.h */
|
||||
int
|
||||
PyErr_CheckSignals(void)
|
||||
{
|
||||
if (!is_main()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _PyErr_CheckSignals();
|
||||
}
|
||||
|
||||
|
||||
/* Declared in cpython/pyerrors.h */
|
||||
int
|
||||
_PyErr_CheckSignals(void)
|
||||
{
|
||||
int i;
|
||||
PyObject *f;
|
||||
|
@ -1613,9 +1634,6 @@ PyErr_CheckSignals(void)
|
|||
if (!_Py_atomic_load(&is_tripped))
|
||||
return 0;
|
||||
|
||||
if (PyThread_get_thread_ident() != main_thread)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The is_tripped variable is meant to speed up the calls to
|
||||
* PyErr_CheckSignals (both directly or via pending calls) when no
|
||||
|
@ -1687,8 +1705,9 @@ int
|
|||
PyOS_InterruptOccurred(void)
|
||||
{
|
||||
if (_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) {
|
||||
if (PyThread_get_thread_ident() != main_thread)
|
||||
if (!is_main()) {
|
||||
return 0;
|
||||
}
|
||||
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1716,12 +1735,13 @@ _PySignal_AfterFork(void)
|
|||
_clear_pending_signals();
|
||||
main_thread = PyThread_get_thread_ident();
|
||||
main_pid = getpid();
|
||||
main_interp = _PyInterpreterState_Get();
|
||||
}
|
||||
|
||||
int
|
||||
_PyOS_IsMainThread(void)
|
||||
{
|
||||
return PyThread_get_thread_ident() == main_thread;
|
||||
return is_main();
|
||||
}
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
|
|
|
@ -379,9 +379,16 @@ handle_signals(void)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Ensure that the thread isn't currently running some other
|
||||
* interpreter.
|
||||
*/
|
||||
if (_PyInterpreterState_GET_UNSAFE() != _PyRuntime.interpreters.main) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
UNSIGNAL_PENDING_SIGNALS();
|
||||
if (PyErr_CheckSignals() < 0) {
|
||||
if (_PyErr_CheckSignals() < 0) {
|
||||
SIGNAL_PENDING_SIGNALS(); /* We're not done yet */
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue