[issue40312] Weakref callbacks running before finalizers in GC collection

Allan Feldman report at bugs.python.org
Sun Apr 19 00:38:57 EDT 2020


Allan Feldman <allan.d.feldman at gmail.com> added the comment:

Reading more carefully, I may have jumped to conclusions here :)

Looking at the weakref docs, I see the following description of the callback functionality:

> If callback is provided and not None, and the returned weakref object is still alive, the callback will be called when the object is about to be finalized; the weak reference object will be passed as the only parameter to the callback; the referent will no longer be available.

This description seems to imply that even if an object is resurrected, the callback will be run.

Using the `ForeverObject` example above, I see the weakref callback behavior is different when going through gc versus going through `_Py_Dealloc`.

The behavior being different seems to imply that a contract is broken somewhere.

In this case I think I assumed it was gc, but it looks like it might actually be that the contract (as currently defined) is broken by dealloc. Finalizers are always called before weakref callbacks on the reference counted path:
https://github.com/python/cpython/blob/482259d0dcf27714a84cf56b93977320bea7e093/Objects/typeobject.c#L1245

Here is the output from the `ForeverObject` example above:

------- Circular reference: True -------
callback running <weakref at 0x10fedea10; dead>
--------------
------- Circular reference: False -------
--------------

For my own understanding, why is the API documented as running the callback prior to finalizers running? The referent is unavailable when the callback runs, so isn't it safe to run the weakref callbacks consistently after the finalizers?

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue40312>
_______________________________________


More information about the Python-bugs-list mailing list