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:
importasyncioasyncdefrepro():
# create a long-running futurelong=asyncio.get_running_loop().create_future()
# create a future shielding itshielded=asyncio.shield(long)
print(len(long._asyncio_awaited_byor [])) # 1print([f.__name__forf, _inlong._callbacks]) # ['_clear_awaited_by_callback', '_inner_done_callback']# cancel and give callbacks a chance to runshielded.cancel()
awaitasyncio.sleep(0.)
# after this really only `_log_on_exception` should remain attached, but...print(len(long._asyncio_awaited_byor [])) # still 1 but I wish it was 0print([f.__name__forf, _inlong._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