diff -r 4c0d38670f41 Lib/test/test_signal.py --- a/Lib/test/test_signal.py Tue Oct 16 22:50:34 2012 +0300 +++ b/Lib/test/test_signal.py Tue Oct 16 17:19:20 2012 -0300 @@ -265,6 +265,42 @@ assert_python_ok('-c', code) + def test_wakeup_read_only_fd(self): + # use a subprocess to have only one thread + code = """if 1: + try: + import fcntl + import sys + import os + import signal + import time + + def handler(signum, frame): + pass + + signal.signal(signal.SIGALRM, handler) + read, write = os.pipe() + for fd in (read, write): + flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) + flags = flags | os.O_NONBLOCK + fcntl.fcntl(fd, fcntl.F_SETFL, flags) + + # set wakeup_fd a read file descriptor to trigger the error + signal.set_wakeup_fd(read) + + signal.alarm(1) + while range(10): + time.sleep(0.2) + + os.close(read) + os.close(write) + sys.exit(-1) + except OSError: + sys.exit(0) + """ + + assert_python_ok('-c', code) + def test_wakeup_fd_early(self): self.check_wakeup("""def test(): import select diff -r 4c0d38670f41 Modules/signalmodule.c --- a/Modules/signalmodule.c Tue Oct 16 22:50:34 2012 +0300 +++ b/Modules/signalmodule.c Tue Oct 16 17:19:20 2012 -0300 @@ -172,15 +172,30 @@ return PyErr_CheckSignals(); } +static int +checksignals_errno(void * unused) +{ + int error = (int) unused; + if (error) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return PyErr_CheckSignals(); +} + static void trip_signal(int sig_num) { unsigned char byte; + int rc = 0; Handlers[sig_num].tripped = 1; if (wakeup_fd != -1) { byte = (unsigned char)sig_num; - write(wakeup_fd, &byte, 1); + while ((rc = write(wakeup_fd, &byte, 1)) == -1 && errno == EINTR); + if (rc == -1) { + Py_AddPendingCall(checksignals_errno, errno); + return; + } } if (is_tripped) return;