python-trio / python-trio/trio

Give a better error for improper combinations of AsyncExitStack with nurseries

Open
#1,243 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Description

Hi all, I ran into a weird issue today. Consider the following program:

import trio
from contextlib import AsyncExitStack


async def start_context(stack):
    nursery = await stack.enter_async_context(trio.open_nursery())
    nursery.start_soon(trio.sleep, 1)


async def main():
    async with AsyncExitStack() as stack:
        async with trio.open_nursery() as nursery:
            nursery.start_soon(start_context, stack)


if __name__ == "__main__":
    trio.run(main)

It opens an AsyncExitStack and uses it to enter a nursery from another task. This produces the following traceback:

Traceback (most recent call last):
  File "/home/vinmic/miniconda/lib/python3.7/site-packages/trio/_core/_run.py", line 1769, in run
    run_impl(runner, async_fn, args)
  File "/home/vinmic/miniconda/lib/python3.7/site-packages/trio/_core/_run.py", line 1918, in run_impl
    runner.task_exited(task, final_outcome)
  File "/home/vinmic/miniconda/lib/python3.7/site-packages/trio/_core/_run.py", line 1391, in task_exited
    self.tasks.remove(task)
KeyError: <Task '__main__.start_context' at 0x7f7883818240>

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

Traceback (most recent call last):
  File "test_trio.py", line 17, in <module>
    trio.run(main)
  File "/home/vinmic/miniconda/lib/python3.7/site-packages/trio/_core/_run.py", line 1775, in run
    ) from exc
trio.TrioInternalError: internal error in Trio - please file a bug!
Exception ignored in: <function Nursery.__del__ at 0x7f7883abca60>
Traceback (most recent call last):
  File "/home/vinmic/miniconda/lib/python3.7/site-packages/trio/_core/_run.py", line 964, in __del__
AssertionError:

I suspect this issue to be caused by the fact the the nursery is not entered and exited in the same task. As far as I understand this is a trio limitation. In this case, a nicer exception could really help :)

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

Start by running the reproducer from the issue, then inspect trio/_core/_run.py at Runner.task_exited and Nursery.del, which appear in the traceback. Trace how the nursery is entered and exited across tasks, and make the improper AsyncExitStack combination produce a clear user-facing exception instead of TrioInternalError; add a regression test for the shown case.

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
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.