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
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_FINALIZEDbit when objects are allocated from free-lists.As far as I can tell, this only affects
PyAsyncGenASendobjects -- I haven't seen other objects that are both allocated from free-lists and usetp_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 thetest(true)call will suppress this warning (if uncommented) because it ensures that there is an already-finalized object in the free-list.Linked PRs