-
-
Notifications
You must be signed in to change notification settings - Fork 362
Open
Labels
Description
contextlib.AsyncExitStack is quite dangerous, in that it makes it very easy to break the nesting structure of context managers. If you manage to do that to a nursery, bad things result:
from contextlib import AsyncExitStack, asynccontextmanager
import trio
async def main():
async with AsyncExitStack() as stack, trio.open_nursery() as nursery:
# The asynccontextmanager is going to create a nursery that outlives this nursery!
nursery.start_soon(
stack.enter_async_context,
asynccontextmanager_that_creates_a_nursery_internally(),
)
@asynccontextmanager
async def asynccontextmanager_that_creates_a_nursery_internally():
async with trio.open_nursery() as nursery:
nursery.start_soon(
print_sleep_print, "task_in_asynccontextmanager_nursery", 2.0
)
yield
async def print_sleep_print(name: str, sleep_time: float):
print(f"{name} is about to sleep for {sleep_time} seconds")
await trio.sleep(sleep_time)
print(f"{name} finished sleeping for {sleep_time} seconds")
if __name__ == "__main__":
trio.run(main)
$ python t.py
task_in_asynccontextmanager_nursery is about to sleep for 2.0 seconds
Traceback (most recent call last):
File ".../python3.11/site-packages/trio/_core/_run.py", line 2872, in unrolled_run
runner.task_exited(task, final_outcome)
File ".../python3.11/site-packages/trio/_core/_run.py", line 2038, in task_exited
self.tasks.remove(task)
KeyError: <Task 'contextlib.AsyncExitStack.enter_async_context' at 0x101b1f3d0>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/zac/code/anthropic/t.py", line 34, in <module>
trio.run(main)
File ".../python3.11/site-packages/trio/_core/_run.py", line 2518, in run
timeout = gen.send(next_send)
^^^^^^^^^^^^^^^^^^^
File ".../python3.11/site-packages/trio/_core/_run.py", line 2928, 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 0x101b2f940>
Traceback (most recent call last):
File ".../python3.11/site-packages/trio/_core/_run.py", line 2136, in init
File ".../python3.11/site-packages/trio/_core/_run.py", line 1109, in __aexit__
File ".../python3.11/site-packages/trio/_core/_run.py", line 1282, in _nested_child_finished
File ".../python3.11/site-packages/trio/_core/_run.py", line 1249, in _add_exc
File ".../python3.11/site-packages/trio/_core/_run.py", line 930, in _cancel
File ".../python3.11/site-packages/trio/_core/_run.py", line 501, in recalculate
File ".../python3.11/site-packages/trio/_core/_run.py", line 1663, in _attempt_delivery_of_any_pending_cancel
File ".../python3.11/site-packages/trio/_core/_run.py", line 1636, in _attempt_abort
File ".../python3.11/site-packages/trio/_core/_io_kqueue.py", line 164, in abort
File ".../python3.11/site-packages/trio/_core/_io_kqueue.py", line 186, in abort
ValueError: I/O operation on closed kqueue object
Exception ignored in: <function Nursery.__del__ at 0x100f8b100>
Traceback (most recent call last):
File ".../python3.11/site-packages/trio/_core/_run.py", line 1480, in __del__
AssertionError:
Exception ignored in: <function Nursery.__del__ at 0x100f8b100>
Traceback (most recent call last):
File ".../python3.11/site-packages/trio/_core/_run.py", line 1480, in __del__
AssertionError:
Exception ignored in: <async_generator object asynccontextmanager_that_creates_a_nursery_internally at 0x102186340>
Traceback (most recent call last):
File ".../python3.11/site-packages/trio/_core/_asyncgens.py", line 112, in finalizer
File ".../python3.11/site-packages/trio/_core/_entry_queue.py", line 148, in run_sync_soon
File ".../python3.11/site-packages/trio/_core/_wakeup_socketpair.py", line 39, in wakeup_thread_and_signal_safe
OSError: [Errno 9] Bad file descriptor
and I think we should check for misnesting on nursery exit so that we can deliver an immediate TrioRuntimeError
(new type?) rather than an internal error further down the line.
It would also be really helpful to (optionally) dump the stack trace of both nurseries as-of-entry, making it obvious exactly where the mis-nesting started.