This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Error in PyGen_NeedsFinalizing()
Type: Stage:
Components: Interpreter Core Versions: Python 2.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: tim.peters, twouters
Priority: high Keywords:

Created on 2006-04-14 19:31 by tim.peters, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
patch.txt tim.peters, 2006-04-14 19:31 enough to make test_generators crash
gen.diff twouters, 2006-04-14 23:22
Messages (3)
msg28241 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2006-04-14 19:31
There's an off-by-one error in PyGen_NeedsFinalizing():
 the loop starts by looking at
f->f_blockstack[f->f_iblock], but that's one beyond the
largest legitimate f_blockstack index.  As a result,
any generator with an active loop is very likely to
claim it needs finalizing (to the extent that it's
unlikely that reading up trash for b_type will match
SETUP_LOOP).

The attached patch repairs that, but also tries to
remove some of the goofy .close() gimmicks added to old
tests in test_generators to worm around "leaks" caused
by that all generators said they needed finalizers in
2.5 at first.  (That's how I bumped into this:  I tried
removing the .close() gimmicks first, but -R:: runs
said they still leaked -- that started the trail
leading to PyGen_NeedsFinalizing()).

Alas, after applying the patch, test_generators craps
out in a debug build with a NULL-pointer dereference in
_Py_ForgetReference(), in the guts of the `if` test
deciding whether to produce an "UNREF invalid object"
error.  At the time, op_type is _PyGen_Type and
op->_ob_next = _ob_prev = NULL, probably meaning that
op was already passed to _Py_ForgetReference() previously.

We get into _Py_ForgetReference() via a chain starting
at the the decref in ceval.c's

	while (STACK_LEVEL() > b->b_level) {
		v = POP();
		Py_XDECREF(v);

and we got into PyEval_EvalFrameEx via gen_send_ex via
gen_close via gen_dealloc via (eventually) a dict on
some instance going away ... and then I got lost. 
Looks like there are several more layers of generator
deallocs on the call stack too.

I'm out of time for looking at this now, so recording
it here.
msg28242 - (view) Author: Thomas Wouters (twouters) * (Python committer) Date: 2006-04-14 23:22
Logged In: YES 
user_id=34209

As explained on python-dev, I believe this patch fixes the
crash. It still leaves test_generators leaking 255
references, though, which I find completely unsurprising
given the pain it's caused so far :) I do believe these
changes are correct even if we don't fix the generator
leakage, but someone with more fundamental knowledge of the
cyclic GC might want to pronounce.
msg28243 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2006-04-15 02:28
Logged In: YES 
user_id=31435

Phillip checked in a related patch that looked good, fixed
the segfaults, and allowed to get rid of the explicit closes
in the LazyList-based examples without new leaking.  (The
tee-based examples still need explicit closing to avoid
leaking, and I added XXX comments about that.)  So, closing
as fixed.

Thanks!
History
Date User Action Args
2022-04-11 14:56:16adminsetgithub: 43209
2006-04-14 19:31:55tim.peterscreate