Hi Antoine, On Sat, May 18, 2013 at 3:45 PM, Antoine Pitrou <solip...@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. _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com