summaryrefslogtreecommitdiffstats
path: root/Objects/genobject.c
diff options
context:
space:
mode:
authorPhillip J. Eby <pje@telecommunity.com>2006-04-15 01:02:17 (GMT)
committerPhillip J. Eby <pje@telecommunity.com>2006-04-15 01:02:17 (GMT)
commit8ebb28df3a6e0bce240b6c2aa20d7aa5a4dfef39 (patch)
tree066424b3c1e37a639145e6453cb4f7d1b83b41e1 /Objects/genobject.c
parent3cfea2dc987b90e637c4cbd5db5dc1f542e448b2 (diff)
downloadcpython-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.c21
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;
}