Kaydet (Commit) 11da8e24 authored tarafından Victor Stinner's avatar Victor Stinner

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.
üst 09354fd6
...@@ -8,6 +8,7 @@ This module allows high-level and efficient I/O multiplexing, built upon the ...@@ -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'): ...@@ -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)
......
...@@ -47,18 +47,6 @@ class TestEPoll(unittest.TestCase): ...@@ -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): ...@@ -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)
......
...@@ -5,7 +5,7 @@ import selectors ...@@ -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): ...@@ -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:
......
...@@ -25,6 +25,11 @@ Core and Builtins ...@@ -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.
......
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