[3.6] bpo-31334: Fix timeout in select.poll.poll() (GH-3277) (#4033) · python/cpython@97abcab (original) (raw)

4 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -211,7 +211,7 @@ def test_threaded_poll(self):
211 211 @unittest.skipUnless(threading, 'Threading required for this test.')
212 212 @reap_threads
213 213 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]:
215 215 # Create two file descriptors. This will be used to unlock
216 216 # the blocking call to poll.poll inside the thread
217 217 r, w = os.pipe()
Original file line number Diff line number Diff line change
@@ -290,6 +290,7 @@ Brad Clements
290 290 Robbie Clemons
291 291 Steve Clift
292 292 Hervé Coatanhay
293 +Riccardo Coccioli
293 294 Nick Coghlan
294 295 Josh Cogliati
295 296 Dave Cole
Original file line number Diff line number Diff 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.
Original file line number Diff line number Diff line change
@@ -528,20 +528,14 @@ poll_poll(pollObject *self, PyObject *args)
528 528 PyObject *result_list = NULL, *timeout_obj = NULL;
529 529 int poll_result, i, j;
530 530 PyObject *value = NULL, *num = NULL;
531 -_PyTime_t timeout, ms, deadline;
531 +_PyTime_t timeout = -1, ms = -1, deadline = 0;
532 532 int async_err = 0;
533 533
534 534 if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) {
535 535 return NULL;
536 536 }
537 537
538 -/* Check values for timeout */
539 -if (timeout_obj == NULL |
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) {
545 539 if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,
546 540 _PyTime_ROUND_TIMEOUT) < 0) {
547 541 if (PyErr_ExceptionMatches(PyExc_TypeError)) {
@@ -557,7 +551,20 @@ poll_poll(pollObject *self, PyObject *args)
557 551 return NULL;
558 552 }
559 553
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
561 568 }
562 569
563 570 /* Avoid concurrent poll() invocation, issue 8865 */