merge
This commit is contained in:
commit
17dd53b464
@ -275,6 +275,57 @@ class WakeupSignalTests(unittest.TestCase):
|
||||
|
||||
assert_python_ok('-c', code)
|
||||
|
||||
def test_wakeup_write_error(self):
|
||||
# Issue #16105: write() errors in the C signal handler should not
|
||||
# pass silently.
|
||||
# Use a subprocess to have only one thread.
|
||||
code = """if 1:
|
||||
import errno
|
||||
import fcntl
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import time
|
||||
from test.support import captured_stderr
|
||||
|
||||
def handler(signum, frame):
|
||||
1/0
|
||||
|
||||
signal.signal(signal.SIGALRM, handler)
|
||||
r, w = os.pipe()
|
||||
flags = fcntl.fcntl(r, fcntl.F_GETFL, 0)
|
||||
fcntl.fcntl(r, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
||||
|
||||
# Set wakeup_fd a read-only file descriptor to trigger the error
|
||||
signal.set_wakeup_fd(r)
|
||||
try:
|
||||
with captured_stderr() as err:
|
||||
signal.alarm(1)
|
||||
time.sleep(5.0)
|
||||
except ZeroDivisionError:
|
||||
# An ignored exception should have been printed out on stderr
|
||||
err = err.getvalue()
|
||||
if ('Exception ignored when trying to write to the signal wakeup fd'
|
||||
not in err):
|
||||
raise AssertionError(err)
|
||||
if ('OSError: [Errno %d]' % errno.EBADF) not in err:
|
||||
raise AssertionError(err)
|
||||
else:
|
||||
raise AssertionError("ZeroDivisionError not raised")
|
||||
"""
|
||||
r, w = os.pipe()
|
||||
try:
|
||||
os.write(r, b'x')
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
self.skipTest("OS doesn't report write() error on the read end of a pipe")
|
||||
finally:
|
||||
os.close(r)
|
||||
os.close(w)
|
||||
|
||||
assert_python_ok('-c', code)
|
||||
|
||||
def test_wakeup_fd_early(self):
|
||||
self.check_wakeup("""def test():
|
||||
import select
|
||||
|
@ -10,6 +10,10 @@ Projected Release date: 2013-09-08
|
||||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #16105: When a signal handler fails to write to the file descriptor
|
||||
registered with ``signal.set_wakeup_fd()``, report an exception instead
|
||||
of ignoring the error.
|
||||
|
||||
- Issue #18722: Remove uses of the "register" keyword in C code.
|
||||
|
||||
- Issue #18667: Add missing "HAVE_FCHOWNAT" symbol to posix._have_functions.
|
||||
|
@ -175,15 +175,31 @@ checksignals_witharg(void * unused)
|
||||
return PyErr_CheckSignals();
|
||||
}
|
||||
|
||||
static int
|
||||
report_wakeup_error(void *data)
|
||||
{
|
||||
int save_errno = errno;
|
||||
errno = (int) (Py_intptr_t) data;
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
PySys_WriteStderr("Exception ignored when trying to write to the "
|
||||
"signal wakeup fd:\n");
|
||||
PyErr_WriteUnraisable(NULL);
|
||||
errno = save_errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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(report_wakeup_error, (void *) (Py_intptr_t) errno);
|
||||
}
|
||||
if (is_tripped)
|
||||
return;
|
||||
|
Loading…
x
Reference in New Issue
Block a user