Skip to content

Add an extra tick for explicit timeouts below resolution — to avoid infinite sleeps - #36

Merged
nolar merged 1 commit into
mainfrom
fix-small-timeouts
Oct 14, 2026
Merged

nolar merged 1 commit into
mainfrom
fix-small-timeouts

Conversation

@nolar

@nolar nolar commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

The issue was caused by misalignment of looptime vs. asyncio: the fractional part of the sleep smaller than the resolution (1e-6 by default) was rounded down to 0, causing 0 ticks of the clock, while asyncio clearly expected the time to move beyond that point, which never happened. Now, it will happen — the clock can move slightly beyond the requested timeout, but at most by 1 tick of the resolution.

A tricky aspect: sometimes, asyncio requested sleeps with floating point precision errors in them (because of its timeout math), and we cannot add 1x extra tick there, since this would break the precise time movements of looptime. Instead, we split that one sleep by an integer number of ticks as usual, and add 1x extra tick only if the requested timeout is explicitly smaller than the resolution, but greater than zero. In other words, when we are sure that asyncio asks for this tiny sleep, and does not inject it because of the floating point math.

The sleeps and timeouts with no fractional parts smaller than the resoltion, should not be affected, as they remain in the integer zone and require no extra ticks.

Closes #35

@nolar nolar added the bug Something isn't working label Oct 14, 2026
@nolar
nolar force-pushed the fix-small-timeouts branch from c1ac453 to 1efb8af Compare October 14, 2026 14:17
@nolar nolar changed the title Ceil the time step instead of rounding — to avoid infinite sleep Add an extra tick for explicit timeouts below resolution — to avoid infinite sleeps Oct 14, 2026
…nfinite sleeps

The issue was caused by misalignment of looptime vs. asyncio: the fractional part of the sleep smaller than the resolution (1e-6 by default) was rounded down to 0, causing 0 ticks of the clock, while asyncio clearly expected the time to move beyond that point, which never happened. Now, it will happen — the clock can move slightly beyond the requested timeout, but at most by 1 tick of the resolution.

A tricky aspect: sometimes, asyncio requested sleeps with floating point precision errors in them (because of its timeout math), and we cannot add 1x extra tick there, since this would break the precise time movements of looptime. Instead, we split that one sleep by an integer number of ticks as usual, and add 1x extra tick only if the requested timeout is explicitly smaller than the resolution, but greater than zero. In other words, when we are sure that asyncio asks for this tiny sleep, and does not inject it because of the floating point math.

The sleeps and timeouts with no fractional parts smaller than the resoltion, should not be affected, as they remain in the integer zone and require no extra ticks.

Signed-off-by: Sergey Vasilyev <nolar@nolar.info>
@nolar
nolar force-pushed the fix-small-timeouts branch from 1efb8af to 56d755c Compare October 14, 2026 14:20
@nolar
nolar merged commit 466c118 into main Oct 14, 2026
12 checks passed
@nolar
nolar deleted the fix-small-timeouts branch October 14, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sleeping for certain times hangs forever

1 participant