Skip to content

Commit 97abcab

Browse files
miss-islingtonserhiy-storchaka
authored andcommitted
[3.6] bpo-31334: Fix timeout in select.poll.poll() (GH-3277) (#4033)
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. (cherry picked from commit 6cfa927)
1 parent be4e9cc commit 97abcab

File tree

4 files changed

+21
-10
lines changed

4 files changed

+21
-10
lines changed

Lib/test/test_poll.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def test_threaded_poll(self):
211211
@unittest.skipUnless(threading, 'Threading required for this test.')
212212
@reap_threads
213213
def test_poll_blocks_with_negative_ms(self):
214-
for timeout_ms in [None, -1, -1.0, -0.1, -1e-100]:
214+
for timeout_ms in [None, -1000, -1, -1.0, -0.1, -1e-100]:
215215
# Create two file descriptors. This will be used to unlock
216216
# the blocking call to poll.poll inside the thread
217217
r, w = os.pipe()

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ Brad Clements
290290
Robbie Clemons
291291
Steve Clift
292292
Hervé Coatanhay
293+
Riccardo Coccioli
293294
Nick Coghlan
294295
Josh Cogliati
295296
Dave Cole
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix ``poll.poll([timeout])`` in the ``select`` module for arbitrary negative
2+
timeouts on all OSes where it can only be a non-negative integer or -1.
3+
Patch by Riccardo Coccioli.

Modules/selectmodule.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -528,20 +528,14 @@ poll_poll(pollObject *self, PyObject *args)
528528
PyObject *result_list = NULL, *timeout_obj = NULL;
529529
int poll_result, i, j;
530530
PyObject *value = NULL, *num = NULL;
531-
_PyTime_t timeout, ms, deadline;
531+
_PyTime_t timeout = -1, ms = -1, deadline = 0;
532532
int async_err = 0;
533533

534534
if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) {
535535
return NULL;
536536
}
537537

538-
/* Check values for timeout */
539-
if (timeout_obj == NULL || timeout_obj == Py_None) {
540-
timeout = -1;
541-
ms = -1;
542-
deadline = 0; /* initialize to prevent gcc warning */
543-
}
544-
else {
538+
if (timeout_obj != NULL && timeout_obj != Py_None) {
545539
if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
546540
_PyTime_ROUND_TIMEOUT) < 0) {
547541
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
@@ -557,7 +551,20 @@ poll_poll(pollObject *self, PyObject *args)
557551
return NULL;
558552
}
559553

560-
deadline = _PyTime_GetMonotonicClock() + timeout;
554+
if (timeout >= 0) {
555+
deadline = _PyTime_GetMonotonicClock() + timeout;
556+
}
557+
}
558+
559+
/* On some OSes, typically BSD-based ones, the timeout parameter of the
560+
poll() syscall, when negative, must be exactly INFTIM, where defined,
561+
or -1. See issue 31334. */
562+
if (ms < 0) {
563+
#ifdef INFTIM
564+
ms = INFTIM;
565+
#else
566+
ms = -1;
567+
#endif
561568
}
562569

563570
/* Avoid concurrent poll() invocation, issue 8865 */

0 commit comments

Comments
 (0)