diff options
author | Phillip J. Eby <pje@telecommunity.com> | 2006-04-15 01:02:17 (GMT) |
---|---|---|
committer | Phillip J. Eby <pje@telecommunity.com> | 2006-04-15 01:02:17 (GMT) |
commit | 8ebb28df3a6e0bce240b6c2aa20d7aa5a4dfef39 (patch) | |
tree | 066424b3c1e37a639145e6453cb4f7d1b83b41e1 /Objects/genobject.c | |
parent | 3cfea2dc987b90e637c4cbd5db5dc1f542e448b2 (diff) | |
download | cpython-8ebb28df3a6e0bce240b6c2aa20d7aa5a4dfef39.zip cpython-8ebb28df3a6e0bce240b6c2aa20d7aa5a4dfef39.tar.gz cpython-8ebb28df3a6e0bce240b6c2aa20d7aa5a4dfef39.tar.bz2 |
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.
Diffstat (limited to 'Objects/genobject.c')
-rw-r--r-- | Objects/genobject.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/Objects/genobject.c b/Objects/genobject.c index ccce315..c73a53cb 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -35,7 +35,7 @@ gen_dealloc(PyGenObject *gen) } _PyObject_GC_UNTRACK(self); - Py_XDECREF(gen->gi_frame); + Py_CLEAR(gen->gi_frame); PyObject_GC_Del(gen); } @@ -130,8 +130,8 @@ gen_close(PyGenObject *gen, PyObject *args) "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 @@ PyDoc_STRVAR(throw_doc, 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 @@ PyTypeObject PyGen_Type = { 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ - + 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ @@ -366,15 +366,16 @@ PyGen_NeedsFinalizing(PyGenObject *gen) 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; } |