Commit 90f6c7e3 authored by Tim Peters's avatar Tim Peters

SF bug 543148: Memory leak with stackframes + inspect.

Put a bound on the number of frameobjects that can live in the
frameobject free_list.

Am also backporting to 2.2.  I don't intend to backport to 2.1 (too
much work -- lots of cyclic structures leak there, and the GC API).
parent a466092f
...@@ -56,9 +56,15 @@ static PyGetSetDef frame_getsetlist[] = { ...@@ -56,9 +56,15 @@ static PyGetSetDef frame_getsetlist[] = {
After all, while a typical program may make millions of calls, a After all, while a typical program may make millions of calls, a
call depth of more than 20 or 30 is probably already exceptional call depth of more than 20 or 30 is probably already exceptional
unless the program contains run-away recursion. I hope. unless the program contains run-away recursion. I hope.
Later, MAXFREELIST was added to bound the # of frames saved on
free_list. Else programs creating lots of cyclic trash involving
frames could provoke free_list into growing without bound.
*/ */
static PyFrameObject *free_list = NULL; static PyFrameObject *free_list = NULL;
static int numfree = 0; /* number of frames currently in free_list */
#define MAXFREELIST 200 /* max value for numfree */
static void static void
frame_dealloc(PyFrameObject *f) frame_dealloc(PyFrameObject *f)
...@@ -91,8 +97,13 @@ frame_dealloc(PyFrameObject *f) ...@@ -91,8 +97,13 @@ frame_dealloc(PyFrameObject *f)
Py_XDECREF(f->f_exc_type); Py_XDECREF(f->f_exc_type);
Py_XDECREF(f->f_exc_value); Py_XDECREF(f->f_exc_value);
Py_XDECREF(f->f_exc_traceback); Py_XDECREF(f->f_exc_traceback);
f->f_back = free_list; if (numfree < MAXFREELIST) {
free_list = f; ++numfree;
f->f_back = free_list;
free_list = f;
}
else
PyObject_GC_Del(f);
Py_TRASHCAN_SAFE_END(f) Py_TRASHCAN_SAFE_END(f)
} }
...@@ -245,6 +256,8 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, ...@@ -245,6 +256,8 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
return NULL; return NULL;
} }
else { else {
assert(numfree > 0);
--numfree;
f = free_list; f = free_list;
free_list = free_list->f_back; free_list = free_list->f_back;
if (f->ob_size < extras) { if (f->ob_size < extras) {
...@@ -475,5 +488,7 @@ PyFrame_Fini(void) ...@@ -475,5 +488,7 @@ PyFrame_Fini(void)
PyFrameObject *f = free_list; PyFrameObject *f = free_list;
free_list = free_list->f_back; free_list = free_list->f_back;
PyObject_GC_Del(f); PyObject_GC_Del(f);
--numfree;
} }
assert(numfree == 0);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment