Skip to content

close() hangs infinitely in nested async context manager #306

@peku33

Description

@peku33

Description

This relatively simple scenario causes the program to lock up in some weird state:

import asyncio
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager

import aiosqlite


@asynccontextmanager
async def acmgr_other() -> AsyncIterator[None]:
    async with asyncio.Lock(): # not actually needed, just to demonstrate any other context manager works
        yield


@asynccontextmanager
async def acmgr_aiosqlite() -> AsyncIterator[None]:
    async with aiosqlite.connect("test.sqlite"):
        yield


@asynccontextmanager
async def acmgr2() -> AsyncIterator[None]:
    async with acmgr_aiosqlite():  # hangs on acmgr_aiosqlite, passes on acmgr_other
        yield


async def gen() -> AsyncIterator[None]:
    async with acmgr2():
        yield None


async def _amain() -> None:
    async for _ in gen():
        raise ValueError()


asyncio.run(_amain())

process never ends.

After some experimenting around with acmgr_aiosqlite it seems like close() causes some weird behaviour around event loop:

@asynccontextmanager
async def acmgr_aiosqlite() -> AsyncIterator[None]:
    connection = await aiosqlite.connect("test.sqlite")

    exc = None
    try:
        yield
    except BaseException as exc2:
        exc = exc2
    finally:
        try:
            print("close() begin")
            await connection.close()
            print("close() end")
        except BaseException as exc2:
            print("exception begin")
            print(exc2, type(exc2))
            print("exception end")
        finally:
            print("finally")

    if exc is not None:
        raise exc

produces

PS path> python .\test4.py
close() begin
Task exception was never retrieved
future: <Task finished name='Task-3' coro=<<async_generator_athrow without __name__>()> exception=RuntimeError('aclose(): asynchronous generator is already running')>
Traceback (most recent call last):
(...)

Details

  • OS: win11
  • Python version: 3.11.9
  • aiosqlite version: 0.20.0
  • Can you repro on 'main' branch? probably yes
  • Can you repro in a clean virtualenv? yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions