summaryrefslogtreecommitdiff
path: root/Modules/signalmodule.c
diff options
context:
space:
mode:
authorAntoine Pitrou <pitrou@free.fr>2017-06-28 23:29:29 +0200
committerGitHub <noreply@github.com>2017-06-28 23:29:29 +0200
commitc08177a1ccad2ed0d50898c2731b518c631aed14 (patch)
treec4f495928530cdffb077bb5bf0cd69d96626f71f /Modules/signalmodule.c
parent9f3bdcb643623e07497af2fc35f0496c2302f1be (diff)
downloadcpython-git-c08177a1ccad2ed0d50898c2731b518c631aed14.tar.gz
bpo-30703: Improve signal delivery (#2415)
* Improve signal delivery Avoid using Py_AddPendingCall from signal handler, to avoid calling signal-unsafe functions. * Remove unused function * Improve comments * Add stress test * Adapt for --without-threads * Add second stress test * Add NEWS blurb * Address comments @haypo
Diffstat (limited to 'Modules/signalmodule.c')
-rw-r--r--Modules/signalmodule.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 75abc98bc4..cbf0d54305 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -189,12 +189,6 @@ It raises KeyboardInterrupt.");
static int
-checksignals_witharg(void * unused)
-{
- return PyErr_CheckSignals();
-}
-
-static int
report_wakeup_write_error(void *data)
{
int save_errno = errno;
@@ -244,17 +238,15 @@ trip_signal(int sig_num)
Handlers[sig_num].tripped = 1;
- if (!is_tripped) {
- /* Set is_tripped after setting .tripped, as it gets
- cleared in PyErr_CheckSignals() before .tripped. */
- is_tripped = 1;
- Py_AddPendingCall(checksignals_witharg, NULL);
- }
+ /* Set is_tripped after setting .tripped, as it gets
+ cleared in PyErr_CheckSignals() before .tripped. */
+ is_tripped = 1;
+ _PyEval_SignalReceived();
/* And then write to the wakeup fd *after* setting all the globals and
- doing the Py_AddPendingCall. We used to write to the wakeup fd and then
- set the flag, but this allowed the following sequence of events
- (especially on windows, where trip_signal runs in a new thread):
+ doing the _PyEval_SignalReceived. We used to write to the wakeup fd
+ and then set the flag, but this allowed the following sequence of events
+ (especially on windows, where trip_signal may run in a new thread):
- main thread blocks on select([wakeup_fd], ...)
- signal arrives
@@ -289,6 +281,8 @@ trip_signal(int sig_num)
wakeup.send_err_set = 1;
wakeup.send_errno = errno;
wakeup.send_win_error = GetLastError();
+ /* Py_AddPendingCall() isn't signal-safe, but we
+ still use it for this exceptional case. */
Py_AddPendingCall(report_wakeup_send_error, NULL);
}
}
@@ -302,6 +296,8 @@ trip_signal(int sig_num)
rc = _Py_write_noraise(fd, &byte, 1);
if (rc < 0) {
+ /* Py_AddPendingCall() isn't signal-safe, but we
+ still use it for this exceptional case. */
Py_AddPendingCall(report_wakeup_write_error,
(void *)(intptr_t)errno);
}
@@ -1556,8 +1552,10 @@ PyErr_CheckSignals(void)
arglist);
Py_DECREF(arglist);
}
- if (!result)
+ if (!result) {
+ is_tripped = 1;
return -1;
+ }
Py_DECREF(result);
}