diff options
author | Antoine Pitrou <pitrou@free.fr> | 2017-06-28 21:29:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-28 21:29:29 (GMT) |
commit | c08177a1ccad2ed0d50898c2731b518c631aed14 (patch) | |
tree | c4f495928530cdffb077bb5bf0cd69d96626f71f /Modules | |
parent | 9f3bdcb643623e07497af2fc35f0496c2302f1be (diff) | |
download | cpython-c08177a1ccad2ed0d50898c2731b518c631aed14.zip cpython-c08177a1ccad2ed0d50898c2731b518c631aed14.tar.gz cpython-c08177a1ccad2ed0d50898c2731b518c631aed14.tar.bz2 |
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')
-rw-r--r-- | Modules/signalmodule.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 75abc98..cbf0d54 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); } |