Skip to content

Commit b33194d

Browse files
committed
call Runner.task_exited on aborted tasks to get errors for aborted tasks and handle nested scenarios (needs test)
1 parent cb1aafc commit b33194d

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

src/trio/_core/_run.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,12 +2018,18 @@ def task_exited(self, task: Task, outcome: Outcome[object]) -> None:
20182018
# avoid internal errors.
20192019
runner = GLOBAL_RUN_CONTEXT.runner
20202020
for nursery in task._child_nurseries:
2021-
nursery.cancel_scope.cancel()
2022-
for child in nursery._children:
2021+
for child in nursery._children.copy():
20232022
if child in runner.runq:
20242023
runner.runq.remove(child)
2025-
runner.tasks.remove(child)
2026-
nursery._children.clear()
2024+
self.task_exited(
2025+
child,
2026+
Error(
2027+
RuntimeError(
2028+
f"Task {child} aborted after nursery was destroyed due to misnesting."
2029+
)
2030+
),
2031+
)
2032+
assert not nursery._children
20272033
try:
20282034
# Raise this, rather than just constructing it, to get a
20292035
# traceback frame included

src/trio/_core/_tests/test_run.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -885,24 +885,32 @@ async def started_sleeper(task_status: _core.TaskStatus[None]) -> None:
885885
async def unstarted_task() -> None:
886886
raise AssertionError("this should not even get a chance to run")
887887

888-
async with AsyncExitStack() as stack:
889-
manager = _core.open_nursery()
890-
nursery = await manager.__aenter__()
891-
# The asynccontextmanager is going to create a nursery that outlives this nursery!
892-
nursery.start_soon(
893-
stack.enter_async_context,
894-
asynccontextmanager_that_creates_a_nursery_internally(),
895-
)
896-
with pytest.RaisesGroup(
888+
with pytest.RaisesGroup(
889+
pytest.RaisesExc(
890+
RuntimeError,
891+
match="Task .*unstarted_task.* aborted after nursery was destroyed due to misnesting.",
892+
),
893+
pytest.RaisesExc(
894+
RuntimeError,
895+
match="Task .*started_sleeper.* aborted after nursery was destroyed due to misnesting.",
896+
),
897+
pytest.RaisesGroup(
897898
pytest.RaisesExc(RuntimeError, match="Nursery stack corrupted")
898-
):
899-
await manager.__aexit__(None, None, None)
899+
),
900+
):
901+
async with AsyncExitStack() as stack, _core.open_nursery() as nursery:
902+
# The asynccontextmanager is going to create a nursery that outlives this nursery!
903+
nursery.start_soon(
904+
stack.enter_async_context,
905+
asynccontextmanager_that_creates_a_nursery_internally(),
906+
)
900907

901908
# The outer nursery forcefully aborts the inner nursery and stops `unstarted_task`
902909
# from ever being started.
910+
# `started_sleeper` is awaited, but not the internal `sleep`
903911
with pytest.warns(
904912
RuntimeWarning,
905-
match="^coroutine 'test_asyncexitstack_nursery_misnest.<locals>.unstarted_task' was never awaited$",
913+
match="^coroutine '(test_asyncexitstack_nursery_misnest.<locals>.unstarted_task|sleep)' was never awaited$",
906914
):
907915
gc_collect_harder()
908916

0 commit comments

Comments
 (0)