python-trio / python-trio/trio

`sleep()` hangs indefinitely when using a custom clock

Open
#3,369 13 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
7.3k
Forks
431
Avg merge
2d 17h
Merged PRs (30d)
6

Description

Tested on 0.32 and the current master.

MRE:

import trio
import trio.testing


class FooMockClock(trio.abc.Clock):
    def __init__(self) -> None:
        self._clock = trio.testing.MockClock(autojump_threshold=0)

    def current_time(self) -> float:
        return self._clock.current_time()

    def deadline_to_sleep_time(self, deadline: float) -> float:
        return self._clock.deadline_to_sleep_time(deadline)

    def start_clock(self) -> None:
        self._clock.start_clock()


async def main():
    print(trio.current_time())
    await trio.sleep(2)
    print(trio.current_time())


if __name__ == '__main__':
    print("MockClock")
    trio.run(main, clock=trio.testing.MockClock(autojump_threshold=0))
    print("FooMockClock")
    trio.run(main, clock=FooMockClock())

Output:

MockClock
0.0
2.0
FooMockClock
0.0
< hangs indefinitely >

I expected the second run() to behave exactly the same as the first. What am I doing wrong?

Also, if I copy-paste trio.testing.MockClock verbatim to this script and use that, the execution crashes - may be related:

Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2813, in unrolled_run
    assert isinstance(runner.clock, _core.MockClock)
AssertionError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/bogdan/wb/github/nucypher-async/t_new.py", line 185, in <module>
    trio.run(main, clock=MockClock(autojump_threshold=0))
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2538, in run
    timeout = gen.send(next_send)
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2951, in unrolled_run
    raise TrioInternalError("internal error in Trio - please file a bug!") from exc
trio.TrioInternalError: internal error in Trio - please file a bug!
Exception ignored in: <coroutine object Runner.init at 0x106a26500>
Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2156, in init
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1112, in __aexit__
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1288, in _nested_child_finished
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1252, in _add_exc
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 933, in _cancel
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 501, in recalculate
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1671, in _attempt_delivery_of_any_pending_cancel
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1644, in _attempt_abort
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_io_kqueue.py", line 162, in abort
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_io_kqueue.py", line 184, in abort
ValueError: I/O operation on closed kqueue object
Exception ignored in: <function Nursery.__del__ at 0x105b208b0>
Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1486, in __del__
AssertionError: 
Exception ignored in: <coroutine object main at 0x106a26570>
Traceback (most recent call last):
  File "/Users/bogdan/wb/github/nucypher-async/t_new.py", line 180, in main
  File "/Users/bogdan/wb/repos/trio/src/trio/_timeouts.py", line 111, in sleep
  File "/Users/bogdan/wb/repos/trio/src/trio/_timeouts.py", line 91, in sleep_until
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 714, in __exit__
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 640, in _close
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2993, in current_task
RuntimeError: must be called from async context
Exception ignored in: <function Nursery.__del__ at 0x105b208b0>
Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1486, in __del__
AssertionError: 
bogdan@lair ~/w/g/nucypher-async (todo-party) [1]> python t_new.py
0.0
Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2813, in unrolled_run
    assert isinstance(runner.clock, _core.MockClock)
AssertionError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/bogdan/wb/github/nucypher-async/t_new.py", line 186, in <module>
    trio.run(main, clock=MockClock(autojump_threshold=0))
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2538, in run
    timeout = gen.send(next_send)
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2951, in unrolled_run
    raise TrioInternalError("internal error in Trio - please file a bug!") from exc
trio.TrioInternalError: internal error in Trio - please file a bug!
Exception ignored in: <coroutine object Runner.init at 0x106ade500>
Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2156, in init
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1112, in __aexit__
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1288, in _nested_child_finished
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1252, in _add_exc
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 933, in _cancel
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 501, in recalculate
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1671, in _attempt_delivery_of_any_pending_cancel
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1644, in _attempt_abort
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_io_kqueue.py", line 162, in abort
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_io_kqueue.py", line 184, in abort
ValueError: I/O operation on closed kqueue object
Exception ignored in: <function Nursery.__del__ at 0x105bd8820>
Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1486, in __del__
AssertionError: 
Exception ignored in: <coroutine object main at 0x106ade570>
Traceback (most recent call last):
  File "/Users/bogdan/wb/github/nucypher-async/t_new.py", line 181, in main
  File "/Users/bogdan/wb/repos/trio/src/trio/_timeouts.py", line 111, in sleep
  File "/Users/bogdan/wb/repos/trio/src/trio/_timeouts.py", line 91, in sleep_until
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 714, in __exit__
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 640, in _close
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 2993, in current_task
RuntimeError: must be called from async context
Exception ignored in: <function Nursery.__del__ at 0x105bd8820>
Traceback (most recent call last):
  File "/Users/bogdan/wb/repos/trio/src/trio/_core/_run.py", line 1486, in __del__
AssertionError: 

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the supplied MRE first, then inspect the clock handling in src/trio/_core/_run.py and the sleep path in src/trio/_timeouts.py. Review the related assertion and cleanup failures in src/trio/_core/_io_kqueue.py. Done means a custom clock and a copied MockClock no longer hang, trigger the internal assertion, or produce the shown cleanup errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.