[Python-checkins] cpython: Issue #20452: select and selectors round (again) timeout away from zero for

victor.stinner python-checkins at python.org
Fri Jan 31 12:19:25 CET 2014


http://hg.python.org/cpython/rev/827d948ac6aa
changeset:   88845:827d948ac6aa
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Fri Jan 31 12:12:53 2014 +0100
summary:
  Issue #20452: select and selectors round (again) timeout away from zero for
poll and epoll

Improve also debug info to analyze the issue

files:
  Lib/asyncio/base_events.py           |  15 +++------
  Lib/selectors.py                     |  10 +++++-
  Lib/test/test_asyncio/test_events.py |  23 ++++++---------
  Modules/selectmodule.c               |   4 ++-
  4 files changed, 26 insertions(+), 26 deletions(-)


diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -627,16 +627,11 @@
             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
--- a/Lib/selectors.py
+++ b/Lib/selectors.py
@@ -8,6 +8,7 @@
 from abc import ABCMeta, abstractmethod, abstractproperty
 from collections import namedtuple, Mapping
 import functools
+import math
 import select
 import sys
 
@@ -369,8 +370,9 @@
             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 @@
                 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
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -28,6 +28,15 @@
 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 @@
         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 @@
 
         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
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -1458,7 +1458,9 @@
         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) {

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list