Author pitrou
Recipients Anssi.Kääriäinen, amaury.forgeotdarc, benjamin.peterson, docs@python, isoschiz, ncoghlan, pconnell, pitrou, vstinner
Date 2013-04-20.11:31:11
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1366457468.2512.15.camel@fsol>
In-reply-to <1366451093.72.0.532401371988.issue17468@psf.upfronthosting.co.za>
Content
> I wonder if it would be better to reword the garbage collection docs
> to mention that Python can't collect objects if they are part of a
> reference cycle, and some of the objects in the reference cycle need
> to run code at gc time. Then mention that such objects include objects
> with __del__ and also generators if they do have some other blocks
> than loops in them (for example try or with blocks).
> 
> To me it seems this issue could be mitigated somewhat by collecting
> the objects if there is just one object with finalizer code in the
> cycle. It should be safe to run the single finalizer, then collect the
> whole cycle, right?

This is tricky because it relies on the fact that the object with
finalizer will be collected before any objects the finalizer relies on.
For a generator, this means it has to be finalized before its frame
object is cleared (otherwise, the finally block can't execute
correctly).

However, the GC doesn't collect those objects directly. It calls
tp_clear on each of them, hoping that tp_clear will break the reference
cycle (and at the same time collect some of the objects in the cycle).
But it's difficult to influence which objects are collected first. 

In gcgen.py's case, the reference cycle is comprised of the MyObj
instance, the generator, and the generator's frame:

  `self` (MyObj) -> generator -> frame -> `self` (MyObj)

So if `self` is collected first, it will collect the generator before
the frame, and the generator's finally block can execute fine.

But if the frame is collected first, it will clear itself and it will be
too late for the generator's finally block to execute.

And if the generator is collected first... well, it can't, as it doesn't
have a tp_clear slot; but if it had, that would clear the frame and make
the finally block uncallable. One might argue that a generator's
tp_clear should call the finally block *before* clearing the frame.
History
Date User Action Args
2013-04-20 11:31:12pitrousetrecipients: + pitrou, amaury.forgeotdarc, ncoghlan, vstinner, benjamin.peterson, docs@python, Anssi.Kääriäinen, pconnell, isoschiz
2013-04-20 11:31:12pitroulinkissue17468 messages
2013-04-20 11:31:11pitroucreate