From: Victor Stinner Date: Wed, 27 Aug 2014 10:59:44 +0000 (+0200) Subject: Issue #22042: signal.set_wakeup_fd(fd) now raises an exception if the file X-Git-Tag: v3.5.0a1~1002 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3822760f2d6ce4ab61daab2ab5ebc83bea839e92;p=python Issue #22042: signal.set_wakeup_fd(fd) now raises an exception if the file descriptor is in blocking mode. --- diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 57b0d8657e..812bd90ee1 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -271,6 +271,9 @@ class WakeupFDTests(unittest.TestCase): self.addCleanup(os.close, r2) self.addCleanup(os.close, w2) + os.set_blocking(w1, False) + os.set_blocking(w2, False) + signal.set_wakeup_fd(w1) self.assertEqual(signal.set_wakeup_fd(w2), w1) self.assertEqual(signal.set_wakeup_fd(-1), w2) @@ -279,10 +282,12 @@ class WakeupFDTests(unittest.TestCase): def test_set_wakeup_fd_socket_result(self): sock1 = socket.socket() self.addCleanup(sock1.close) + sock1.setblocking(False) fd1 = sock1.fileno() sock2 = socket.socket() self.addCleanup(sock2.close) + sock2.setblocking(False) fd2 = sock2.fileno() signal.set_wakeup_fd(fd1) @@ -290,6 +295,26 @@ class WakeupFDTests(unittest.TestCase): self.assertEqual(signal.set_wakeup_fd(-1), fd2) self.assertEqual(signal.set_wakeup_fd(-1), -1) + # On Windows, files are always blocking and Windows does not provide a + # function to test if a socket is in non-blocking mode. + @unittest.skipIf(sys.platform == "win32", "tests specific to POSIX") + def test_set_wakeup_fd_blocking(self): + rfd, wfd = os.pipe() + self.addCleanup(os.close, rfd) + self.addCleanup(os.close, wfd) + + # fd must be non-blocking + os.set_blocking(wfd, True) + with self.assertRaises(ValueError) as cm: + signal.set_wakeup_fd(wfd) + self.assertEqual(str(cm.exception), + "the fd %s must be in non-blocking mode" % wfd) + + # non-blocking is ok + os.set_blocking(wfd, False) + signal.set_wakeup_fd(wfd) + signal.set_wakeup_fd(-1) + @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") class WakeupSignalTests(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index 09afd98463..f9ead1c8a9 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -124,6 +124,9 @@ Core and Builtins Library ------- +- Issue #22042: signal.set_wakeup_fd(fd) now raises an exception if the file + descriptor is in blocking mode. + - Issue #16808: inspect.stack() now returns a named tuple instead of a tuple. Patch by Daniel Shahaf. diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 61b3330d3f..38c5d21cba 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -561,9 +561,15 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args) PyErr_SetFromErrno(PyExc_OSError); return NULL; } + + /* on Windows, a file cannot be set to non-blocking mode */ } - else + else { is_socket = 1; + + /* Windows does not provide a function to test if a socket + is in non-blocking mode */ + } } old_fd = wakeup.fd; @@ -576,6 +582,8 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args) return PyLong_FromLong(-1); #else if (fd != -1) { + int blocking; + if (!_PyVerify_fd(fd)) { PyErr_SetString(PyExc_ValueError, "invalid fd"); return NULL; @@ -585,6 +593,16 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args) PyErr_SetFromErrno(PyExc_OSError); return NULL; } + + blocking = _Py_get_blocking(fd); + if (blocking < 0) + return NULL; + if (blocking) { + PyErr_Format(PyExc_ValueError, + "the fd %i must be in non-blocking mode", + fd); + return NULL; + } } old_fd = wakeup_fd;