Issue #20311: selector.PollSelector.select() now rounds the timeout away from

zero, instead of rounding towards zero. For example, a timeout of one
microsecond is now rounded to one millisecond, instead of being rounded to
zero.

Move also a test in test_epoll which was moved by my previous merge.
This commit is contained in:
Victor Stinner 2014-01-21 01:48:28 +01:00
parent 09354fd606
commit 11da8e24ba
4 changed files with 40 additions and 14 deletions

View file

@ -8,6 +8,7 @@ This module allows high-level and efficient I/O multiplexing, built upon the
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from collections import namedtuple, Mapping from collections import namedtuple, Mapping
import functools import functools
import math
import select import select
import sys import sys
@ -351,7 +352,12 @@ if hasattr(select, 'poll'):
return key return key
def select(self, timeout=None): def select(self, timeout=None):
timeout = None if timeout is None else max(int(1000 * timeout), 0) if timeout is None:
timeout = None
elif timeout < 0:
timeout = 0
else:
timeout = int(math.ceil(timeout * 1000.0))
ready = [] ready = []
try: try:
fd_event_list = self._poll.poll(timeout) fd_event_list = self._poll.poll(timeout)

View file

@ -47,18 +47,6 @@ class TestEPoll(unittest.TestCase):
self.serverSocket.listen(1) self.serverSocket.listen(1)
self.connections = [self.serverSocket] self.connections = [self.serverSocket]
def test_timeout_rounding(self):
# epoll_wait() has a resolution of 1 millisecond, check if the timeout
# is correctly rounded to the upper bound
epoll = select.epoll()
self.addCleanup(epoll.close)
for timeout in (1e-2, 1e-3, 1e-4):
t0 = time.perf_counter()
epoll.poll(timeout)
dt = time.perf_counter() - t0
self.assertGreaterEqual(dt, timeout)
def tearDown(self): def tearDown(self):
for skt in self.connections: for skt in self.connections:
skt.close() skt.close()
@ -266,6 +254,17 @@ class TestEPoll(unittest.TestCase):
self.addCleanup(epoll.close) self.addCleanup(epoll.close)
self.assertEqual(os.get_inheritable(epoll.fileno()), False) self.assertEqual(os.get_inheritable(epoll.fileno()), False)
def test_timeout_rounding(self):
# epoll_wait() has a resolution of 1 millisecond, check if the timeout
# is correctly rounded to the upper bound
epoll = select.epoll()
self.addCleanup(epoll.close)
for timeout in (1e-2, 1e-3, 1e-4):
t0 = time.perf_counter()
epoll.poll(timeout)
dt = time.perf_counter() - t0
self.assertGreaterEqual(dt, timeout)
def test_main(): def test_main():
support.run_unittest(TestEPoll) support.run_unittest(TestEPoll)

View file

@ -5,7 +5,7 @@ import selectors
import signal import signal
import socket import socket
from test import support from test import support
from time import sleep from time import sleep, perf_counter
import unittest import unittest
import unittest.mock import unittest.mock
try: try:
@ -363,6 +363,22 @@ class BaseSelectorTestCase(unittest.TestCase):
self.assertFalse(s.select(2)) self.assertFalse(s.select(2))
self.assertLess(time() - t, 2.5) self.assertLess(time() - t, 2.5)
def test_timeout_rounding(self):
# Issue #20311: Timeout must be rounded away from zero to wait *at
# least* timeout seconds. For example, epoll_wait() has a resolution of
# 1 ms (10^-3), epoll.select(0.0001) must wait 1 ms, not 0 ms.
s = self.SELECTOR()
self.addCleanup(s.close)
rd, wr = self.make_socketpair()
s.register(rd, selectors.EVENT_READ)
for timeout in (1e-2, 1e-3, 1e-4):
t0 = perf_counter()
s.select(timeout)
dt = perf_counter() - t0
self.assertGreaterEqual(dt, timeout)
class ScalableSelectorMixIn: class ScalableSelectorMixIn:

View file

@ -25,6 +25,11 @@ Core and Builtins
Library Library
------- -------
- Issue #20311: selector.PollSelector.select() now rounds the timeout away from
zero, instead of rounding towards zero. For example, a timeout of one
microsecond is now rounded to one millisecond, instead of being rounded to
zero.
- Issue #20311: select.epoll.poll() now rounds the timeout away from zero, - Issue #20311: select.epoll.poll() now rounds the timeout away from zero,
instead of rounding towards zero. For example, a timeout of one microsecond instead of rounding towards zero. For example, a timeout of one microsecond
is now rounded to one millisecond, instead of being rounded to zero. is now rounded to one millisecond, instead of being rounded to zero.