summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_signal.py25
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/signalmodule.c20
3 files changed, 47 insertions, 1 deletions
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;