Skip to content

Commit 1a0d657

Browse files
committed
Fix #259: handle large timeouts in loop.call_later()
1 parent ee02de2 commit 1a0d657

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

tests/test_base.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,37 @@ def custom_handler(loop, context):
740740
self.assertIs(type(_context['context']['exception']),
741741
ZeroDivisionError)
742742

743+
def test_big_call_later_timeout(self):
744+
OK, NOT_OK = 0, 0
745+
746+
async def sleep(delay_name, delay):
747+
nonlocal OK, NOT_OK
748+
try:
749+
await asyncio.sleep(delay)
750+
except asyncio.CancelledError:
751+
OK += 1
752+
except Exception:
753+
NOT_OK += 1
754+
755+
async def main():
756+
tests = [
757+
sleep("infinity", float("inf")),
758+
sleep("sys.maxsize", float(sys.maxsize)),
759+
sleep("sys.maxsize", sys.maxsize),
760+
sleep("2**55", 2**55),
761+
sleep("2**54", 2**54),
762+
]
763+
tasks = [self.loop.create_task(test) for test in tests]
764+
await asyncio.sleep(0.1)
765+
for task in tasks:
766+
task.cancel()
767+
await task
768+
769+
self.loop.run_until_complete(main())
770+
771+
self.assertEqual(OK, 5)
772+
self.assertEqual(NOT_OK, 0)
773+
743774

744775
class TestBaseAIO(_TestBase, AIOTestCase):
745776
pass

uvloop/loop.pyx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ include "errors.pyx"
5050
cdef:
5151
int PY37 = PY_VERSION_HEX >= 0x03070000
5252
int PY36 = PY_VERSION_HEX >= 0x03060000
53+
uint64_t MAX_SLEEP = 3600 * 24 * 365 * 100
5354

5455

5556
cdef _is_sock_stream(sock_type):
@@ -1271,10 +1272,10 @@ cdef class Loop:
12711272

12721273
if delay < 0:
12731274
delay = 0
1274-
elif delay == py_inf:
1275+
elif delay == py_inf or delay > MAX_SLEEP:
12751276
# ~100 years sounds like a good approximation of
12761277
# infinity for a Python application.
1277-
delay = 3600 * 24 * 365 * 100
1278+
delay = MAX_SLEEP
12781279

12791280
when = <uint64_t>round(delay * 1000)
12801281
if not args:

0 commit comments

Comments
 (0)