[Python-checkins] r45409 - in python/trunk: Lib/test/test_generators.py Objects/frameobject.c Objects/genobject.c (original) (raw)
phillip.eby python-checkins at python.org
Sat Apr 15 03:02:21 CEST 2006
- Previous message: [Python-checkins] buildbot failure in x86 W2k trunk
- Next message: [Python-checkins] buildbot warnings in x86 XP trunk
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Author: phillip.eby Date: Sat Apr 15 03:02:17 2006 New Revision: 45409
Modified: python/trunk/Lib/test/test_generators.py python/trunk/Objects/frameobject.c python/trunk/Objects/genobject.c Log: Fix SF#1470508: crash in generator cycle finalization. There were two problems: first, PyGen_NeedsFinalizing() had an off-by-one bug that prevented it from ever saying a generator didn't need finalizing, and second, frame objects cleared themselves in a way that caused their owning generator to think they were still executable, causing a double deallocation of objects on the value stack if there was still a loop on the block stack. This revision also removes some unnecessary close() operations from test_generators that are now appropriately handled by the cycle collector.
Modified: python/trunk/Lib/test/test_generators.py
--- python/trunk/Lib/test/test_generators.py (original) +++ python/trunk/Lib/test/test_generators.py Sat Apr 15 03:02:17 2006 @@ -421,7 +421,6 @@ ... self.name = name ... self.parent = None ... self.generator = self.generate() -... self.close = self.generator.close ... ... def generate(self): ... while not self.parent: @@ -484,8 +483,6 @@ merged A into G A->G B->G C->G D->G E->G F->G G->G H->G I->G J->G K->G L->G M->G ->>> for s in sets: s.close() # break cycles
""" # Emacs turd ' @@ -593,7 +590,6 @@ ... def init(self, g): ... self.sofar = [] ... self.fetch = g.next -... self.close = g.close ... ... def getitem(self, i): ... sofar, fetch = self.sofar, self.fetch @@ -624,8 +620,6 @@ [200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384] [400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675] ->>> m235.close()
Ye olde Fibonacci generator, LazyList style.
def fibgen(a, b): @@ -648,7 +642,6 @@ fib = LazyList(fibgen(1, 2)) firstn(iter(fib), 17) [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584] ->>> fib.close()
Running after your tail with itertools.tee (new in version 2.4)
Modified: python/trunk/Objects/frameobject.c
--- python/trunk/Objects/frameobject.c (original) +++ python/trunk/Objects/frameobject.c Sat Apr 15 03:02:17 2006 @@ -454,9 +454,15 @@ static void frame_clear(PyFrameObject *f) { - PyObject **fastlocals, **p; + PyObject **fastlocals, **p, **oldtop; int i, slots;
- oldtop = f->f_stacktop;
- /* Before anything else, make sure that this frame is clearly marked
as being defunct! */
f->f_stacktop = NULL;
Py_XDECREF(f->f_exc_type); f->f_exc_type = NULL;
@@ -473,17 +479,13 @@ slots = f->f_nlocals + f->f_ncells + f->f_nfreevars; fastlocals = f->f_localsplus; for (i = slots; --i >= 0; ++fastlocals) { - if (*fastlocals != NULL) { - Py_XDECREF(*fastlocals); - *fastlocals = NULL; - } + Py_CLEAR(*fastlocals); }
/* stack */
- if (f->f_stacktop != NULL) {
for (p = f->f_valuestack; p < f->f_stacktop; p++) {
Py_XDECREF(*p);
*p = NULL;
- if (oldtop != NULL) {
for (p = f->f_valuestack; p < oldtop; p++) {
}Py_CLEAR(*p); } }
Modified: python/trunk/Objects/genobject.c
--- python/trunk/Objects/genobject.c (original) +++ python/trunk/Objects/genobject.c Sat Apr 15 03:02:17 2006 @@ -35,7 +35,7 @@ } _PyObject_GC_UNTRACK(self); - Py_XDECREF(gen->gi_frame); + Py_CLEAR(gen->gi_frame); PyObject_GC_Del(gen); } @@ -130,8 +130,8 @@ "generator ignored GeneratorExit"); return NULL; } - if ( PyErr_ExceptionMatches(PyExc_StopIteration) - || PyErr_ExceptionMatches(PyExc_GeneratorExit) ) + if ( PyErr_ExceptionMatches(PyExc_StopIteration) + || PyErr_ExceptionMatches(PyExc_GeneratorExit) ) { PyErr_Clear(); /* ignore these errors */ Py_INCREF(Py_None); @@ -208,7 +208,7 @@ return next yielded value or raise StopIteration."); static PyObject * -gen_throw(PyGenObject *gen, PyObject *args) +gen_throw(PyGenObject *gen, PyObject *args) { PyObject *typ; PyObject tb = NULL; @@ -328,7 +328,7 @@ 0, / tp_getset / 0, / tp_base / 0, / tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */
@@ -366,15 +366,16 @@ int i; PyFrameObject *f = gen->gi_frame;
- if (f == NULL || f->f_stacktop==NULL || f->f_iblock<=0)
return 0; /* no frame or no blockstack == no finalization */
- if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0)
return 0; /* no frame or empty blockstack == no finalization */
- for (i=f->f_iblock; i>=0; i--) {
- /* Any block type besides a loop requires cleanup. */
- i = f->f_iblock;
- while (--i >= 0) { if (f->f_blockstack[i].b_type != SETUP_LOOP)
/* any block type besides a loop requires cleanup */ return 1; }
/* No blocks except loops, it's safe to skip finalization */
- /* No blocks except loops, it's safe to skip finalization. */ return 0; }
- Previous message: [Python-checkins] buildbot failure in x86 W2k trunk
- Next message: [Python-checkins] buildbot warnings in x86 XP trunk
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]