Index: Python/sigcheck.c =================================================================== --- Python/sigcheck.c (revision 59439) +++ Python/sigcheck.c (working copy) @@ -17,3 +17,6 @@ PyErr_SetNone(PyExc_KeyboardInterrupt); return -1; } + +int Py_signal_pipe = -1; + Index: Include/pyerrors.h =================================================================== --- Include/pyerrors.h (revision 59439) +++ Include/pyerrors.h (working copy) @@ -238,6 +238,11 @@ PyAPI_FUNC(int) PyErr_CheckSignals(void); PyAPI_FUNC(void) PyErr_SetInterrupt(void); +/* Read end of a pipe used to notify the main thread / main loop that + there are pending signals; Equal to -1 if the platform doesn't + support signals. */ +PyAPI_DATA(int) Py_signal_pipe; + /* Support for adding program text to SyntaxErrors */ PyAPI_FUNC(void) PyErr_SyntaxLocation(const char *, int); PyAPI_FUNC(PyObject *) PyErr_ProgramText(const char *, int); Index: Modules/signalmodule.c =================================================================== --- Modules/signalmodule.c (revision 59439) +++ Modules/signalmodule.c (working copy) @@ -11,6 +11,8 @@ #endif #include +#include +#include #ifndef SIG_ERR #define SIG_ERR ((PyOS_sighandler_t)(-1)) @@ -88,7 +90,10 @@ static PyOS_sighandler_t old_siginthandler = SIG_DFL; +int Py_signal_pipe = -1; /* read end */ +static int Py_signal_pipe_w; /* write end */ + static PyObject * signal_default_int_handler(PyObject *self, PyObject *args) { @@ -112,6 +117,7 @@ static void signal_handler(int sig_num) { + char dummy_char; #ifdef WITH_THREAD #ifdef WITH_PTH if (PyThread_get_thread_ident() != main_thread) { @@ -125,6 +131,7 @@ is_tripped++; Handlers[sig_num].tripped = 1; Py_AddPendingCall(checksignals_witharg, NULL); + write(Py_signal_pipe_w, &dummy_char, sizeof(dummy_char)); #ifdef WITH_THREAD } #endif @@ -309,6 +316,7 @@ { PyObject *m, *d, *x; int i; + int filedes[2], fd_flags; #ifdef WITH_THREAD main_thread = PyThread_get_thread_ident(); @@ -336,6 +344,30 @@ goto finally; Py_DECREF(x); + +#define set_nonblock(fd) \ + if ((fd_flags = fcntl(fd, F_GETFL, 0)) == -1) { \ + PyErr_SetFromErrno(PyExc_RuntimeError); \ + return; \ + } \ + fd_flags |= O_NONBLOCK; \ + if (fcntl(fd, F_SETFL, fd_flags) == -1) { \ + PyErr_SetFromErrno(PyExc_RuntimeError); \ + return; \ + } + + if (Py_signal_pipe == -1) { + if (pipe(filedes)) { + PyErr_SetFromErrno(PyExc_RuntimeError); + return; + } + set_nonblock(filedes[0]); + set_nonblock(filedes[1]); + Py_signal_pipe = filedes[0]; + Py_signal_pipe_w = filedes[1]; + } +#undef set_nonblock + x = IntHandler = PyDict_GetItemString(d, "default_int_handler"); if (!x) goto finally; @@ -592,6 +624,7 @@ int PyErr_CheckSignals(void) { + char dummy_c; int i; PyObject *f; @@ -621,6 +654,11 @@ Py_DECREF(result); } } + /* Flush all bytes from the pipe, so that it stops notifying + * main threads / main loops that signals are pending. */ + while (read(Py_signal_pipe, &dummy_c, sizeof(dummy_c)) == sizeof(dummy_c)) + ; /* pass */ + is_tripped = 0; return 0; }