Skip to content

OverflowError with asyncio.sleep #259

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

Activity

  1. 1st1 commented on Jul 30, 2019

    @1st1
    Member

    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.

    Yeah, makes sense. Care to make a PR?

  2. added 3 commits that reference this issue on Oct 24, 2019
    97dc7f8
    28fd3c5
    1a0d657
  3. reopened this on Oct 25, 2019
  4. 1st1 commented on Oct 25, 2019

    @1st1
    Member

    I've just published https://github.com/MagicStack/uvloop/releases/tag/v0.14.0rc1. Please test. The final release will be published some time next week if RC1 is OK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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