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).
This commit is contained in:
parent
8b1c47bb8b
commit
b7ba743312
@ -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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user