diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-04-28-01-23-38.bpo-43963.u5Y6bS.rst b/Misc/NEWS.d/next/Core and Builtins/2021-04-28-01-23-38.bpo-43963.u5Y6bS.rst new file mode 100644 index 00000000000..1f8904338f2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-04-28-01-23-38.bpo-43963.u5Y6bS.rst @@ -0,0 +1,2 @@ +Importing the :mod:`_signal` module in a subinterpreter has no longer side +effects. diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 98a938f1976..861871332c2 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1543,6 +1543,46 @@ signal_add_constants(PyObject *module) } +static int +signal_get_set_handlers(PyObject *mod_dict) +{ + // Get signal handlers + for (int signum = 1; signum < NSIG; signum++) { + void (*c_handler)(int) = PyOS_getsig(signum); + PyObject *func; + if (c_handler == SIG_DFL) { + func = DefaultHandler; + } + else if (c_handler == SIG_IGN) { + func = IgnoreHandler; + } + else { + func = Py_None; // None of our business + } + // If signal_module_exec() is called more than one, we must + // clear the strong reference to the previous function. + PyObject* old_func = get_handler(signum); + SetHandler(signum, Py_NewRef(func)); + Py_XDECREF(old_func); + } + + // Instal Python SIGINT handler which raises KeyboardInterrupt + PyObject* sigint_func = get_handler(SIGINT); + if (sigint_func == DefaultHandler) { + PyObject *int_handler = PyMapping_GetItemString(mod_dict, + "default_int_handler"); + if (!int_handler) { + return -1; + } + + SetHandler(SIGINT, int_handler); + Py_DECREF(sigint_func); + PyOS_setsig(SIGINT, signal_handler); + } + return 0; +} + + static int signal_module_exec(PyObject *m) { @@ -1571,37 +1611,11 @@ signal_module_exec(PyObject *m) } #endif - // Get signal handlers - for (int signum = 1; signum < NSIG; signum++) { - void (*c_handler)(int) = PyOS_getsig(signum); - PyObject *func; - if (c_handler == SIG_DFL) { - func = DefaultHandler; - } - else if (c_handler == SIG_IGN) { - func = IgnoreHandler; - } - else { - func = Py_None; // None of our business - } - // If signal_module_exec() is called more than one, we must - // clear the strong reference to the previous function. - PyObject* old_func = get_handler(signum); - SetHandler(signum, Py_NewRef(func)); - Py_XDECREF(old_func); - } - - // Instal Python SIGINT handler which raises KeyboardInterrupt - PyObject* sigint_func = get_handler(SIGINT); - if (sigint_func == DefaultHandler) { - PyObject *int_handler = PyMapping_GetItemString(d, "default_int_handler"); - if (!int_handler) { + PyThreadState *tstate = _PyThreadState_GET(); + if (_Py_IsMainInterpreter(tstate->interp)) { + if (signal_get_set_handlers(d) < 0) { return -1; } - - SetHandler(SIGINT, int_handler); - Py_DECREF(sigint_func); - PyOS_setsig(SIGINT, signal_handler); } assert(!PyErr_Occurred());