[Python-Dev] Debugging opportunity :-)
Phillip J. Eby
pje at telecommunity.com
Sat Apr 15 01:30:01 CEST 2006
At 01:11 AM 4/15/2006 +0200, Thomas Wouters wrote:
>On 4/15/06, Thomas Wouters <<mailto:thomas at python.org>thomas at python.org>
>wrote:
>>(I first thought the problem was caused by gen_dealloc doing
>>'Py_DECREF(gen->gen_frame)' instead of 'frame = gen->gen_frame;
>>gen->gen_frame = NULL; Py_DECREF(frame)', but that isn't the case. It
>>should do it that way, I believe, but it's not the cause of this crash.)
>
>fixes the crash.Ah, found the problem. After I hit 'send', I realized I
>hadn't checked frameobject's tp_clear, and sure enough, it calls
>Py_XDECREF in-place. That explains why the first generator object gets
>dealloced twice, although it doesn't explain why it doesn't blow up when
>it reaches a negative refcount.
You're missing another piece of the puzzle: the problem is that since
generators don't have a tp_clear, they don't know they're pointing to an
invalid frame; it appears to still be running. So when the frame object
releases items off the stack, it releases its reference to the generator,
which is released normally, dropping out the local variable reference back
to the generator whose frame is being cleared. That generator doesn't know
it's holding a garbage frame, and thus proceeds to finalize it by resuming
it... which then pops the blockstack, and f_stacktop is still valid, so
popping the blockstack decrefs the frame a second time.
> Fixing frameobject and genobject to both use Py_CLEAR() makes both the
> 'minimal' testcase and test_generators work.
It seems to me that frame_clear() should also set f_stacktop to NULL before
doing any clearing; otherwise it's possible for a generator to think that
the frame is still executable, and the double-decref could thus be replaced
by a null pointer dereference.
More information about the Python-Dev
mailing list