Skip to content

asyncio.BaseEventLoop _clock_resolution has no effect #116342

@KholdStare

Description

@KholdStare

Bug report

Bug description:

Short Version

Adding _clock_resolution in this line has no effect (at least on linux):

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:

# 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

No one assigned

    Labels

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions