Commit 6cfa927c authored by Riccardo Coccioli's avatar Riccardo Coccioli Committed by Victor Stinner

bpo-31334: Fix timeout in select.poll.poll() (GH-3277)

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.
parent 2c15b29a
...@@ -207,7 +207,7 @@ class PollTests(unittest.TestCase): ...@@ -207,7 +207,7 @@ class PollTests(unittest.TestCase):
@unittest.skipUnless(threading, 'Threading required for this test.') @unittest.skipUnless(threading, 'Threading required for this test.')
@reap_threads @reap_threads
def test_poll_blocks_with_negative_ms(self): 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 # Create two file descriptors. This will be used to unlock
# the blocking call to poll.poll inside the thread # the blocking call to poll.poll inside the thread
r, w = os.pipe() r, w = os.pipe()
......
...@@ -292,6 +292,7 @@ Brad Clements ...@@ -292,6 +292,7 @@ Brad Clements
Robbie Clemons Robbie Clemons
Steve Clift Steve Clift
Hervé Coatanhay Hervé Coatanhay
Riccardo Coccioli
Nick Coghlan Nick Coghlan
Josh Cogliati Josh Cogliati
Dave Cole Dave Cole
......
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.
...@@ -525,20 +525,14 @@ poll_poll(pollObject *self, PyObject *args) ...@@ -525,20 +525,14 @@ poll_poll(pollObject *self, PyObject *args)
PyObject *result_list = NULL, *timeout_obj = NULL; PyObject *result_list = NULL, *timeout_obj = NULL;
int poll_result, i, j; int poll_result, i, j;
PyObject *value = NULL, *num = NULL; PyObject *value = NULL, *num = NULL;
_PyTime_t timeout, ms, deadline; _PyTime_t timeout = -1, ms = -1, deadline = 0;
int async_err = 0; int async_err = 0;
if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) { if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) {
return NULL; return NULL;
} }
/* Check values for timeout */ if (timeout_obj != NULL && timeout_obj != Py_None) {
if (timeout_obj == NULL || timeout_obj == Py_None) {
timeout = -1;
ms = -1;
deadline = 0; /* initialize to prevent gcc warning */
}
else {
if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj, if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
_PyTime_ROUND_TIMEOUT) < 0) { _PyTime_ROUND_TIMEOUT) < 0) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) { if (PyErr_ExceptionMatches(PyExc_TypeError)) {
...@@ -554,7 +548,20 @@ poll_poll(pollObject *self, PyObject *args) ...@@ -554,7 +548,20 @@ poll_poll(pollObject *self, PyObject *args)
return NULL; 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 */ /* Avoid concurrent poll() invocation, issue 8865 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment