Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b7ba743

Browse files
committed
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).
1 parent 8b1c47b commit b7ba743

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

Objects/frameobject.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ static PyGetSetDef frame_getsetlist[] = {
5656
After all, while a typical program may make millions of calls, a
5757
call depth of more than 20 or 30 is probably already exceptional
5858
unless the program contains run-away recursion. I hope.
59+
60+
Later, MAXFREELIST was added to bound the # of frames saved on
61+
free_list. Else programs creating lots of cyclic trash involving
62+
frames could provoke free_list into growing without bound.
5963
*/
6064

6165
static PyFrameObject *free_list = NULL;
66+
static int numfree = 0; /* number of frames currently in free_list */
67+
#define MAXFREELIST 200 /* max value for numfree */
6268

6369
static void
6470
frame_dealloc(PyFrameObject *f)
@@ -91,8 +97,13 @@ frame_dealloc(PyFrameObject *f)
9197
Py_XDECREF(f->f_exc_type);
9298
Py_XDECREF(f->f_exc_value);
9399
Py_XDECREF(f->f_exc_traceback);
94-
f->f_back = free_list;
95-
free_list = f;
100+
if (numfree < MAXFREELIST) {
101+
++numfree;
102+
f->f_back = free_list;
103+
free_list = f;
104+
}
105+
else
106+
PyObject_GC_Del(f);
96107
Py_TRASHCAN_SAFE_END(f)
97108
}
98109

@@ -245,6 +256,8 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
245256
return NULL;
246257
}
247258
else {
259+
assert(numfree > 0);
260+
--numfree;
248261
f = free_list;
249262
free_list = free_list->f_back;
250263
if (f->ob_size < extras) {
@@ -475,5 +488,7 @@ PyFrame_Fini(void)
475488
PyFrameObject *f = free_list;
476489
free_list = free_list->f_back;
477490
PyObject_GC_Del(f);
491+
--numfree;
478492
}
493+
assert(numfree == 0);
479494
}

0 commit comments

Comments
 (0)