[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