Description
Bug report
CPython uses freelists to speed up allocation of certain frequently allocated types of objects. CPython also supports finalizers (i.e., tp_finalize
) that are only called once, even if the object is resurrected by its finalizer. These two features do not work well together as currently implemented because we don't clear the _PyGC_PREV_MASK_FINALIZED
bit when objects are allocated from free-lists.
As far as I can tell, this only affects PyAsyncGenASend
objects -- I haven't seen other objects that are both allocated from free-lists and use tp_finalize
.
The finalizer for PyAsyncGenASend
(which may issue a warning), may not be called if the object is allocated from a free-list (and already finalized):
Test case
The test(False)
call should issue a warning about unawaited "asend" coroutine. However, the presence of the test(true)
call will suppress this warning (if uncommented) because it ensures that there is an already-finalized object in the free-list.
import asyncio def main(): loop = asyncio.new_event_loop() async def gen(): yield 1 async def test(do_await): g = gen() if do_await: r = await g.asend(None) else: g.asend(None) await g.aclose() # Uncommenting this line prevents the warning on the following call # due to the already finalized PyAsyncGenASend object in the free-list. # loop.run_until_complete(test(True)) # This should warn! loop.run_until_complete(test(False)) loop.close() if __name__ == '__main__': main()
Linked PRs
Metadata
Metadata
Assignees
Labels
Projects
Status