Bug report
Bug description:
This is basically gh-152569 but for asyncio.shield, and with two leakage mechanisms:
- The calling task (
cur_task) is stored in inner._asyncio_awaited_by and not removed until inner is done.
- The calling task is captured by
_clear_awaited_by_callback which lives in inner._callbacks until inner is done.
Reproducer:
import asyncio
async def repro():
# create a long-running future
long = asyncio.get_running_loop().create_future()
# create a future shielding it
shielded = asyncio.shield(long)
print(len(long._asyncio_awaited_by or [])) # 1
print([f.__name__ for f, _ in long._callbacks]) # ['_clear_awaited_by_callback', '_inner_done_callback']
# cancel and give callbacks a chance to run
shielded.cancel()
await asyncio.sleep(0.)
# after this really only `_log_on_exception` should remain attached, but...
print(len(long._asyncio_awaited_by or [])) # still 1 but I wish it was 0
print([f.__name__ for f, _ in long._callbacks]) # ['_clear_awaited_by_callback', '_log_on_exception']
asyncio.run(repro())
This is tested on 3.14.3, and I checked that the definition of asyncio.tasks.shield has not changed between that and current main (fd9feab at the time I'm writing this).
CPython versions tested on:
3.14
Operating systems tested on:
Linux
Linked PRs
Bug report
Bug description:
This is basically gh-152569 but for
asyncio.shield, and with two leakage mechanisms:cur_task) is stored ininner._asyncio_awaited_byand not removed untilinneris done._clear_awaited_by_callbackwhich lives ininner._callbacksuntilinneris done.Reproducer:
This is tested on 3.14.3, and I checked that the definition of
asyncio.tasks.shieldhas not changed between that and current main (fd9feab at the time I'm writing this).CPython versions tested on:
3.14
Operating systems tested on:
Linux
Linked PRs