]> granicus.if.org Git - python/commitdiff
bpo-31334: Fix timeout in select.poll.poll() (GH-3277)
authorRiccardo Coccioli <volans-@users.noreply.github.com>
Tue, 17 Oct 2017 19:45:07 +0000 (21:45 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Tue, 17 Oct 2017 19:45:07 +0000 (12:45 -0700)
Always pass -1, or INFTIM where defined, to the poll() system call when
a negative timeout is passed to the poll.poll([timeout]) method in the
select module. Various OSes throw an error with arbitrary negative
values.

Lib/test/test_poll.py
Misc/ACKS
Misc/NEWS.d/next/Library/2017-09-04-00-22-31.bpo-31334.9WYRfi.rst [new file with mode: 0644]
Modules/selectmodule.c

index 028dd2d08a3d5179689f13f96e43c1844da94117..d593495a999f20c350f67bc41aadd87e4bc6f535 100644 (file)
@@ -207,7 +207,7 @@ class PollTests(unittest.TestCase):
     @unittest.skipUnless(threading, 'Threading required for this test.')
     @reap_threads
     def test_poll_blocks_with_negative_ms(self):
-        for timeout_ms in [None, -1, -1.0, -0.1, -1e-100]:
+        for timeout_ms in [None, -1000, -1, -1.0, -0.1, -1e-100]:
             # Create two file descriptors. This will be used to unlock
             # the blocking call to poll.poll inside the thread
             r, w = os.pipe()
index 38f68aca214611fe003b07e0e59f46ea1d4c0497..8b9f62eaf7d1e582756f466769e26f43a69b9a2b 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -292,6 +292,7 @@ Brad Clements
 Robbie Clemons
 Steve Clift
 HervĂ© Coatanhay
+Riccardo Coccioli
 Nick Coghlan
 Josh Cogliati
 Dave Cole
diff --git a/Misc/NEWS.d/next/Library/2017-09-04-00-22-31.bpo-31334.9WYRfi.rst b/Misc/NEWS.d/next/Library/2017-09-04-00-22-31.bpo-31334.9WYRfi.rst
new file mode 100644 (file)
index 0000000..1cbfd25
--- /dev/null
@@ -0,0 +1,3 @@
+Fix ``poll.poll([timeout])`` in the ``select`` module for arbitrary negative
+timeouts on all OSes where it can only be a non-negative integer or -1.
+Patch by Riccardo Coccioli.
index 530552324be2872f337daae5e60187ab2818ac3c..0f353fbe84184463a1a1eb400ce693fb9fc4250f 100644 (file)
@@ -525,20 +525,14 @@ poll_poll(pollObject *self, PyObject *args)
     PyObject *result_list = NULL, *timeout_obj = NULL;
     int poll_result, i, j;
     PyObject *value = NULL, *num = NULL;
-    _PyTime_t timeout, ms, deadline;
+    _PyTime_t timeout = -1, ms = -1, deadline = 0;
     int async_err = 0;
 
     if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) {
         return NULL;
     }
 
-    /* Check values for timeout */
-    if (timeout_obj == NULL || timeout_obj == Py_None) {
-        timeout = -1;
-        ms = -1;
-        deadline = 0;   /* initialize to prevent gcc warning */
-    }
-    else {
+    if (timeout_obj != NULL && timeout_obj != Py_None) {
         if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
                                            _PyTime_ROUND_TIMEOUT) < 0) {
             if (PyErr_ExceptionMatches(PyExc_TypeError)) {
@@ -554,7 +548,20 @@ poll_poll(pollObject *self, PyObject *args)
             return NULL;
         }
 
-        deadline = _PyTime_GetMonotonicClock() + timeout;
+        if (timeout >= 0) {
+            deadline = _PyTime_GetMonotonicClock() + timeout;
+        }
+    }
+
+    /* On some OSes, typically BSD-based ones, the timeout parameter of the
+       poll() syscall, when negative, must be exactly INFTIM, where defined,
+       or -1. See issue 31334. */
+    if (ms < 0) {
+#ifdef INFTIM
+        ms = INFTIM;
+#else
+        ms = -1;
+#endif
     }
 
     /* Avoid concurrent poll() invocation, issue 8865 */