Variety of small INC/DECREF patches that fix reported memory leaks
with free variables. Thanks to Martin v. Loewis for finding two of the problems. This fixes SF buf 405583. There is also a C API change: PyFrame_New() is reverting to its pre-2.1 signature. The change introduced by nested scopes was a mistake. XXX Is this okay between beta releases? cell_clear(), the GC helper, must decref its reference to break cycles. frame_dealloc() must dealloc all cell vars and free vars in addition to locals. eval_code2() setup code must INCREF cells it copies out of the closure. The STORE_DEREF opcode implementation must DECREF the object it passes to PyCell_Set().
This commit is contained in:
parent
93fe96a3c8
commit
30c9f3991c
|
@ -46,8 +46,7 @@ extern DL_IMPORT(PyTypeObject) PyFrame_Type;
|
|||
#define PyFrame_Check(op) ((op)->ob_type == &PyFrame_Type)
|
||||
|
||||
DL_IMPORT(PyFrameObject *) PyFrame_New(PyThreadState *, PyCodeObject *,
|
||||
PyObject *, PyObject *,
|
||||
PyObject *);
|
||||
PyObject *, PyObject *);
|
||||
|
||||
|
||||
/* The rest of the interface is specific for frame objects */
|
||||
|
|
|
@ -356,9 +356,6 @@ call_with_frame(PyCodeObject *c, PyObject* func, PyObject* args)
|
|||
c, /*code*/
|
||||
tstate->frame->f_globals, /*globals*/
|
||||
NULL /*locals*/
|
||||
#if PYTHON_API_VERSION >= 1010
|
||||
,NULL /*closure*/
|
||||
#endif
|
||||
);
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
|
|
@ -83,6 +83,7 @@ cell_traverse(PyCellObject *op, visitproc visit, void *arg)
|
|||
static int
|
||||
cell_clear(PyCellObject *op)
|
||||
{
|
||||
Py_XDECREF(op->ob_ref);
|
||||
op->ob_ref = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -65,13 +65,14 @@ static PyFrameObject *free_list = NULL;
|
|||
static void
|
||||
frame_dealloc(PyFrameObject *f)
|
||||
{
|
||||
int i;
|
||||
int i, slots;
|
||||
PyObject **fastlocals;
|
||||
|
||||
Py_TRASHCAN_SAFE_BEGIN(f)
|
||||
/* Kill all local variables */
|
||||
slots = f->f_nlocals + f->f_ncells + f->f_nfreevars;
|
||||
fastlocals = f->f_localsplus;
|
||||
for (i = f->f_nlocals; --i >= 0; ++fastlocals) {
|
||||
for (i = slots; --i >= 0; ++fastlocals) {
|
||||
Py_XDECREF(*fastlocals);
|
||||
}
|
||||
|
||||
|
@ -108,7 +109,7 @@ PyTypeObject PyFrame_Type = {
|
|||
|
||||
PyFrameObject *
|
||||
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
|
||||
PyObject *locals, PyObject *closure)
|
||||
PyObject *locals)
|
||||
{
|
||||
PyFrameObject *back = tstate->frame;
|
||||
static PyObject *builtin_object;
|
||||
|
|
|
@ -430,7 +430,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
|
||||
f = PyFrame_New(tstate, /*back*/
|
||||
co, /*code*/
|
||||
globals, locals, closure);
|
||||
globals, locals);
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -578,8 +578,11 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
}
|
||||
if (f->f_nfreevars) {
|
||||
int i;
|
||||
for (i = 0; i < f->f_nfreevars; ++i)
|
||||
freevars[f->f_ncells + i] = PyTuple_GET_ITEM(closure, i);
|
||||
for (i = 0; i < f->f_nfreevars; ++i) {
|
||||
PyObject *o = PyTuple_GET_ITEM(closure, i);
|
||||
Py_INCREF(o);
|
||||
freevars[f->f_ncells + i] = o;
|
||||
}
|
||||
}
|
||||
|
||||
if (tstate->sys_tracefunc != NULL) {
|
||||
|
@ -1662,7 +1665,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
err = -1;
|
||||
break;
|
||||
}
|
||||
Py_INCREF(w);
|
||||
PUSH(w);
|
||||
break;
|
||||
|
||||
|
@ -1670,6 +1672,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
w = POP();
|
||||
x = freevars[oparg];
|
||||
PyCell_Set(x, w);
|
||||
Py_DECREF(w);
|
||||
continue;
|
||||
|
||||
case BUILD_TUPLE:
|
||||
|
|
Loading…
Reference in New Issue