[Python-Dev] PEP 442: Safe object finalization (original) (raw)

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 gcrefs field of each CI object is initialized to its obrefcnt (again). Then, tptraverse is called on each CI object, and each visited CI object has its gcrefs decremented. This substracts CI-internal references from the gcrefs fields. At the end of the traversal, if all CI objects have their gcrefs 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 gcrefs, 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