-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
Description
Bug report
Bug description:
Short Version
Adding _clock_resolution in this line has no effect (at least on linux):
cpython/Lib/asyncio/base_events.py
Line 1987 in 88b5c66
| end_time = self.time() + self._clock_resolution |
Because time() returns a float of the current epoch time, and clock resolution is 1e-9, self.time() == self.time() + self._clock_resolution, due to floating point precision loss. In a corner case where self.time() matches the next scheduled timer exactly, it would have to wait for the next iteration of the event loop to get run.
Longer Version
I was writing deterministic unittests involving timers and asyncio. I used a VirtualClock which would mock out loop.time() and loop.select():
https://aiotools.readthedocs.io/en/latest/_modules/aiotools/timer.html#VirtualClock
The internal time does not advance unless a timer is awaited.
Unfortunately when using realistic timestamps, because of the precision loss described above, the event loop gets permanently stuck at the exact time of the next timer, and never advances.
In the snippet below, the problem is that handle._when >= end_time is always true:
cpython/Lib/asyncio/base_events.py
Lines 1986 to 1994 in 88b5c66
| # Handle 'later' callbacks that are ready. | |
| end_time = self.time() + self._clock_resolution | |
| while self._scheduled: | |
| handle = self._scheduled[0] | |
| if handle._when >= end_time: | |
| break | |
| handle = heapq.heappop(self._scheduled) | |
| handle._scheduled = False | |
| self._ready.append(handle) |
This was introduced in this change:
ed1654f
CPython versions tested on:
3.10
Operating systems tested on:
Linux
Metadata
Metadata
Assignees
Labels
Projects
Status