Skip to content

OverflowError with asyncio.sleep #259

Closed
@Edward-Knight

Description

@Edward-Knight
  • uvloop version: 0.12.2
  • Python version: 3.7.3
  • Platform: darwin (OSX)
  • Can you reproduce the bug with PYTHONASYNCIODEBUG in env?: yes

This issue is related to #102 ("Should float("inf") for timeout raise an Overflow error?")

uvloop throws an OverflowError if you pass asyncio.sleep a large enough delay.
Thanks to #102, uvloop handles the float("inf") case, but other large numbers (like sys.maxsize) still cause an exception to be thrown.

uvloop/uvloop/loop.pyx

Lines 1287 to 1294 in 88608b8

if delay < 0:
delay = 0
elif delay == py_inf:
# ~100 years sounds like a good approximation of
# infinity for a Python application.
delay = 3600 * 24 * 365 * 100
when = <uint64_t>round(delay * 1000)

Perhaps if round(delay * 1000) is greater than 2^64 − 1, it should be reduced to be equal to that, to avoid OverflowErrors from occurring.

Here is some code to reproduce the error:

import asyncio
import uvloop
import sys


async def sleep(delay_name, delay):
    log_msg = f"Sleep {delay_name} {type(delay).__name__} {delay}"
    try:
        await asyncio.sleep(delay)
    except asyncio.CancelledError:
        print(f"{log_msg}: OK")
    except Exception as e:
        print(f"{log_msg}: {e.__class__.__name__}: {e}")


async def main():
    tests = [
        sleep("infinity", float("inf")),
        sleep("sys.maxsize", float(sys.maxsize)),
        sleep("sys.maxsize", sys.maxsize),
        sleep("2**55", 2**55),
        sleep("2**54", 2**54),
    ]
    tasks = [asyncio.create_task(test) for test in tests]
    await asyncio.sleep(1)
    for task in tasks:
        task.cancel()
        await task


if __name__ == "__main__":
    uvloop.install()
    asyncio.run(main())

It produces the output:

Sleep sys.maxsize float 9.223372036854776e+18: OverflowError: Python int too large to convert to C unsigned long
Sleep sys.maxsize int 9223372036854775807: OverflowError: Python int too large to convert to C unsigned long
Sleep 2**55 int 36028797018963968: OverflowError: Python int too large to convert to C unsigned long
Sleep infinity float inf: OK
Sleep 2**54 int 18014398509481984: OK

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions