summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-01-31 11:12:53 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-01-31 11:12:53 (GMT)
commitdcd9740ad2932f4049e912d8721933696373fe4c (patch)
tree2827fc31b7e57e7bac925f338303c8acf33a1011
parent31f65044a977307915412edffddcb4962a8928a3 (diff)
downloadcpython-dcd9740ad2932f4049e912d8721933696373fe4c.zip
cpython-dcd9740ad2932f4049e912d8721933696373fe4c.tar.gz
cpython-dcd9740ad2932f4049e912d8721933696373fe4c.tar.bz2
Issue #20452: select and selectors round (again) timeout away from zero for
poll and epoll Improve also debug info to analyze the issue
-rw-r--r--Lib/asyncio/base_events.py15
-rw-r--r--Lib/selectors.py10
-rw-r--r--Lib/test/test_asyncio/test_events.py23
-rw-r--r--Modules/selectmodule.c4
4 files changed, 26 insertions, 26 deletions
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 4b8e3fe..05a4c38 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -627,16 +627,11 @@ class BaseEventLoop(events.AbstractEventLoop):
t1 = self.time()
# FIXME: remove these debug info (issue #20452)
dt = t1-t0
- if timeout is not None:
- if dt < timeout and not event_list:
- print("WARNING: selector.select(timeout=%.20f) took dt=%.20f sec (dt-timeout=%+.20f)"
- % (timeout, dt, dt-timeout), file=sys.__stdout__)
- print("WARNING: dt+%.20f > timeout? %s"
- % (self._granularity, (dt + self._granularity) > timeout), file=sys.__stdout__)
- else:
- if not event_list:
- print("WARNING: selector.select(timeout=%r) took dt=%.20f sec"
- % (timeout, dt), file=sys.__stdout__)
+ if timeout is not None and dt < timeout and not event_list:
+ print("WARNING: selector.select(timeout=%.20f) took dt=%.20f sec (dt-timeout=%+.20f)"
+ % (timeout, dt, dt-timeout), file=sys.__stdout__)
+ print("WARNING: dt+%.20f > timeout? %s"
+ % (self._granularity, (dt + self._granularity) > timeout), file=sys.__stdout__)
if t1-t0 >= 1:
level = logging.INFO
else:
diff --git a/Lib/selectors.py b/Lib/selectors.py
index b1b530a..52ee8db 100644
--- a/Lib/selectors.py
+++ b/Lib/selectors.py
@@ -8,6 +8,7 @@ This module allows high-level and efficient I/O multiplexing, built upon the
from abc import ABCMeta, abstractmethod, abstractproperty
from collections import namedtuple, Mapping
import functools
+import math
import select
import sys
@@ -369,8 +370,9 @@ if hasattr(select, 'poll'):
elif timeout <= 0:
timeout = 0
else:
- # Round towards zero
- timeout = int(timeout * 1000)
+ # poll() has a resolution of 1 millisecond, round away from
+ # zero to wait *at least* timeout seconds.
+ timeout = int(math.ceil(timeout * 1e3))
ready = []
try:
fd_event_list = self._poll.poll(timeout)
@@ -430,6 +432,10 @@ if hasattr(select, 'epoll'):
timeout = -1
elif timeout <= 0:
timeout = 0
+ else:
+ # epoll_wait() has a resolution of 1 millisecond, round away
+ # from zero to wait *at least* timeout seconds.
+ timeout = math.ceil(timeout * 1e3) * 1e-3
max_ev = len(self._fd_to_key)
ready = []
try:
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index aef4993..f0781ab 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -28,6 +28,15 @@ from asyncio import events
from asyncio import selector_events
from asyncio import test_utils
+# FIXME: remove these info, used for debug purpose (issue #20452)
+print("time.monotonic() info: %r" % (time.get_clock_info('monotonic'),))
+try:
+ SC_CLK_TCK = os.sysconf('SC_CLK_TCK')
+ print("os.sysconf('SC_CLK_TCK') = %s" % SC_CLK_TCK)
+except Exception:
+ pass
+# FIXME: remove these info, used for debug purpose (issue #20452)
+
def data_file(filename):
if hasattr(support, 'TEST_HOME_DIR'):
@@ -1157,11 +1166,6 @@ class EventLoopTestsMixin:
w.close()
def test_timeout_rounding(self):
- # FIXME: remove this imports, used for debug purpose (issue #20452)
- import time
- import platform
- import os
-
def _run_once():
self.loop._run_once_counter += 1
orig_run_once()
@@ -1182,17 +1186,10 @@ class EventLoopTestsMixin:
self.loop.run_until_complete(wait())
calls.append(self.loop._run_once_counter)
- try:
- SC_CLK_TCK = os.sysconf('SC_CLK_TCK')
- except Exception:
- SC_CLK_TCK = None
self.assertEqual(calls, [1, 3, 5, 6],
# FIXME: remove these info, used for debug purpose (issue #20452)
(self.loop._granularity,
- self.loop._selector.resolution,
- time.get_clock_info('monotonic'),
- SC_CLK_TCK,
- platform.platform()))
+ self.loop._selector.resolution))
class SubprocessTestsMixin:
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
index d44e8de..0c9b9d9 100644
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -1458,7 +1458,9 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
return NULL;
}
else {
- timeout = (int)(dtimeout * 1000.0);
+ /* epoll_wait() has a resolution of 1 millisecond, round away from zero
+ to wait *at least* dtimeout seconds. */
+ timeout = (int)ceil(dtimeout * 1000.0);
}
if (maxevents == -1) {