Internal error: assert len(runner.tasks) == 2
The following piece of code occasionally results in a TrioInternalError which is a bug per exception description:
import trio
from contextlib import AsyncExitStack
DEFAULT_PG_UNIX_SOCKET = '/var/run/postgresql/.s.PGSQL.5432'
class Connection:
def __init__(self):
self._stream = None
self._nursery = None
self._stack = None
async def _run(self):
await self._connect()
while True:
await trio.sleep(1)
async def _connect(self):
self.unix_socket_path = DEFAULT_PG_UNIX_SOCKET
self._stream = await trio.open_unix_socket(
self.unix_socket_path)
async def __aenter__(self):
self._stack = AsyncExitStack()
nursery = trio.open_nursery()
self._nursery = await self._stack.enter_async_context(nursery)
self._nursery.start_soon(self._run)
return self
async def __aexit__(self, exc_type, exc, tb):
#if self._stream:
await self._stream.close()
await self._stack.aclose()
async def main():
async with Connection() as conn:
pass
if __name__ == '__main__':
trio.run(main)
If the commented line is uncommented (and the next line indented), this won't happen. The code sometimes results in an AttributeError, but at other times throws this:
Traceback (most recent call last):
File "/home/mostafa/source/pgtrio/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 2203, in unrolled_run
runner.task_exited(task, final_outcome)
File "/home/mostafa/source/pgtrio/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 1515, in task_exited
outcome.unwrap()
File "/home/mostafa/source/pgtrio/venv/lib/python3.8/site-packages/outcome/_impl.py", line 138, in unwrap
raise captured_error
File "/home/mostafa/source/pgtrio/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 1622, in init
await self.asyncgens.finalize_remaining(self)
File "/home/mostafa/source/pgtrio/venv/lib/python3.8/site-packages/trio/_core/_asyncgens.py", line 122, in finalize_remaining
assert len(runner.tasks) == 2
AssertionError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "bug.py", line 42, in <module>
trio.run(main)
File "/home/mostafa/source/pgtrio/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 1937, in run
timeout = gen.send(next_send)
File "/home/mostafa/source/pgtrio/venv/lib/python3.8/site-packages/trio/_core/_run.py", line 2258, 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!
Raising an error from within your __aexit__ instead of closing the stack violates Trio's (Python's, really) core assumptions about how context managers are supposed to be nested / exceptions to be handled.
This is not a Trio problem. This is a "Doctor, it hurts when I do that." "Don't do that, then" problem.
Right. I've fixed the original problem of course. Just filed the issue because the exception told me to! :)