Issue #20452: select and selectors round (again) timeout away from zero for
poll and epoll Improve also debug info to analyze the issue
This commit is contained in:
parent
31f65044a9
commit
dcd9740ad2
|
@ -627,16 +627,11 @@ class BaseEventLoop(events.AbstractEventLoop):
|
||||||
t1 = self.time()
|
t1 = self.time()
|
||||||
# FIXME: remove these debug info (issue #20452)
|
# FIXME: remove these debug info (issue #20452)
|
||||||
dt = t1-t0
|
dt = t1-t0
|
||||||
if timeout is not None:
|
if timeout is not None and dt < timeout and not event_list:
|
||||||
if dt < timeout and not event_list:
|
print("WARNING: selector.select(timeout=%.20f) took dt=%.20f sec (dt-timeout=%+.20f)"
|
||||||
print("WARNING: selector.select(timeout=%.20f) took dt=%.20f sec (dt-timeout=%+.20f)"
|
% (timeout, dt, dt-timeout), file=sys.__stdout__)
|
||||||
% (timeout, dt, dt-timeout), file=sys.__stdout__)
|
print("WARNING: dt+%.20f > timeout? %s"
|
||||||
print("WARNING: dt+%.20f > timeout? %s"
|
% (self._granularity, (dt + self._granularity) > timeout), file=sys.__stdout__)
|
||||||
% (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 t1-t0 >= 1:
|
if t1-t0 >= 1:
|
||||||
level = logging.INFO
|
level = logging.INFO
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -8,6 +8,7 @@ This module allows high-level and efficient I/O multiplexing, built upon the
|
||||||
from abc import ABCMeta, abstractmethod, abstractproperty
|
from abc import ABCMeta, abstractmethod, abstractproperty
|
||||||
from collections import namedtuple, Mapping
|
from collections import namedtuple, Mapping
|
||||||
import functools
|
import functools
|
||||||
|
import math
|
||||||
import select
|
import select
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -369,8 +370,9 @@ if hasattr(select, 'poll'):
|
||||||
elif timeout <= 0:
|
elif timeout <= 0:
|
||||||
timeout = 0
|
timeout = 0
|
||||||
else:
|
else:
|
||||||
# Round towards zero
|
# poll() has a resolution of 1 millisecond, round away from
|
||||||
timeout = int(timeout * 1000)
|
# zero to wait *at least* timeout seconds.
|
||||||
|
timeout = int(math.ceil(timeout * 1e3))
|
||||||
ready = []
|
ready = []
|
||||||
try:
|
try:
|
||||||
fd_event_list = self._poll.poll(timeout)
|
fd_event_list = self._poll.poll(timeout)
|
||||||
|
@ -430,6 +432,10 @@ if hasattr(select, 'epoll'):
|
||||||
timeout = -1
|
timeout = -1
|
||||||
elif timeout <= 0:
|
elif timeout <= 0:
|
||||||
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)
|
max_ev = len(self._fd_to_key)
|
||||||
ready = []
|
ready = []
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -28,6 +28,15 @@ from asyncio import events
|
||||||
from asyncio import selector_events
|
from asyncio import selector_events
|
||||||
from asyncio import test_utils
|
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):
|
def data_file(filename):
|
||||||
if hasattr(support, 'TEST_HOME_DIR'):
|
if hasattr(support, 'TEST_HOME_DIR'):
|
||||||
|
@ -1157,11 +1166,6 @@ class EventLoopTestsMixin:
|
||||||
w.close()
|
w.close()
|
||||||
|
|
||||||
def test_timeout_rounding(self):
|
def test_timeout_rounding(self):
|
||||||
# FIXME: remove this imports, used for debug purpose (issue #20452)
|
|
||||||
import time
|
|
||||||
import platform
|
|
||||||
import os
|
|
||||||
|
|
||||||
def _run_once():
|
def _run_once():
|
||||||
self.loop._run_once_counter += 1
|
self.loop._run_once_counter += 1
|
||||||
orig_run_once()
|
orig_run_once()
|
||||||
|
@ -1182,17 +1186,10 @@ class EventLoopTestsMixin:
|
||||||
|
|
||||||
self.loop.run_until_complete(wait())
|
self.loop.run_until_complete(wait())
|
||||||
calls.append(self.loop._run_once_counter)
|
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],
|
self.assertEqual(calls, [1, 3, 5, 6],
|
||||||
# FIXME: remove these info, used for debug purpose (issue #20452)
|
# FIXME: remove these info, used for debug purpose (issue #20452)
|
||||||
(self.loop._granularity,
|
(self.loop._granularity,
|
||||||
self.loop._selector.resolution,
|
self.loop._selector.resolution))
|
||||||
time.get_clock_info('monotonic'),
|
|
||||||
SC_CLK_TCK,
|
|
||||||
platform.platform()))
|
|
||||||
|
|
||||||
|
|
||||||
class SubprocessTestsMixin:
|
class SubprocessTestsMixin:
|
||||||
|
|
|
@ -1458,7 +1458,9 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
if (maxevents == -1) {
|
||||||
|
|
Loading…
Reference in New Issue