[Python-Dev] PEP 442: Safe object finalization

Armin Rigo arigo at tunes.org
Sat May 18 16:22:55 CEST 2013


Hi Antoine,

On Sat, May 18, 2013 at 3:45 PM, Antoine Pitrou <solipsis at pitrou.net> wrote:
>> How is this done?  I don't see a clear way to determine it by looking
>> only at the objects in the CI, given that arbitrary modifications of
>> the object graph may have occurred.
>
> The same way a generation is traversed, but restricted to the CI.
>
> First the gc_refs field of each CI object is initialized to its
> ob_refcnt (again).
>
> Then, tp_traverse is called on each CI object, and each visited
> CI object has its gc_refs decremented. This substracts CI-internal
> references from the gc_refs fields.
>
> At the end of the traversal, if all CI objects have their gc_refs equal
> to 0, then the CI has no external reference to it and can be cleared.
> If at least one CI object has non-zero gc_refs, the CI cannot be
> cleared.

Ok, indeed.  Then you really should call finalizers only once: in case
one of the finalizers in a cycle did a trivial change like I
described, the algorithm above will conservatively assume the cycle
should be kept alive.  At the next GC collection we must not call the
finalizer again, because it's likely to just do a similar trivial
change.

(There are other open questions about calling finalizers multiple
times; e.g. an instance of this class has its finalizer called ad
infinitum and leaks, even though X() is never part of any cycle:

class X(object):
   def __del__(self):
      print "tick"
      lst = [self]
      lst.append(lst)

Try interactively: every gc.collect() prints "tick", even if you make
only one instance.)


A bientôt,

Armin.


More information about the Python-Dev mailing list