achimnol / aiotools

Idiomatic asyncio utilties
https://aiotools.readthedocs.io
MIT License
154 stars 12 forks source link

Use set instead of WeakSet in TaskGroup #60

Open heckad opened 1 year ago

heckad commented 1 year ago

Fix bug with tasks leaking from a TaskGroup.

achimnol commented 1 year ago

Um.. could you explain more context on this change? Because weakref.WeakSet is a deliberate choice to prevent memory leaks by allowing task objects garbage-collected right after they finish.

heckad commented 11 months ago

Sorry for the late response. We just updated to python3.11 to solve the problem but here's a minimal MRE

import asyncio
import gc
import weakref

import aiotools

all_features = weakref.WeakSet()

async def inf_loop(future):
    while True:
        print("Message")
        await future

async def inner_scope(tg: aiotools.TaskGroup):
    future = asyncio.Future()

    tg.create_task(inf_loop(future))

    all_features.add(future)

async def main():
    try:
        async with aiotools.TaskGroup() as tg:
            await inner_scope(tg)
            await asyncio.sleep(1)
            gc.collect()
            print("collected")

            raise asyncio.CancelledError
    except asyncio.CancelledError:
        pass

asyncio.run(main(), debug=True)

With standard task group all good but on python3.10 with task group from aiotools we got Task was destroyed but it is pending!