From: Tim Peters Date: Sat, 13 Apr 2002 05:25:28 +0000 (+0000) Subject: SF bug 543148: Memory leak with stackframes + inspect. X-Git-Tag: v2.2.2b1~455 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=19b08d3b3baeaa8931773dc0538aca89405bdd05;p=thirdparty%2FPython%2Fcpython.git SF bug 543148: Memory leak with stackframes + inspect. Put a bound on the number of frameobjects that can live in the frameobject free_list. Also fixed on the trunk. I don't intend to backport to 2.1 (too much work -- lots of cyclic structures leak there). --- diff --git a/Misc/NEWS b/Misc/NEWS index 09b68097c775..6411be870fc0 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -1,3 +1,22 @@ +What's New in Python 2.2.2? +Release date: dd-mmm-2002 +=========================== + +Core and builtins + +- Repaired a slow memory leak possible only in programs creating a + great many cyclic structures involving frames. Reported on + SourceForge as bug 543148. + +Library + + +C API + + +Windows + + What's New in Python 2.2.1 final? Release date: 10-Apr-2002 ================================= diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 8e4c60ff2722..165121d8f871 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -56,9 +56,15 @@ static PyGetSetDef frame_getsetlist[] = { After all, while a typical program may make millions of calls, a call depth of more than 20 or 30 is probably already exceptional 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 int numfree = 0; /* number of frames currently in free_list */ +#define MAXFREELIST 200 /* max value for numfree */ static void frame_dealloc(PyFrameObject *f) @@ -91,8 +97,13 @@ frame_dealloc(PyFrameObject *f) Py_XDECREF(f->f_exc_type); Py_XDECREF(f->f_exc_value); Py_XDECREF(f->f_exc_traceback); - f->f_back = free_list; - free_list = f; + if (numfree < MAXFREELIST) { + ++numfree; + f->f_back = free_list; + free_list = f; + } + else + PyObject_GC_Del(f); Py_TRASHCAN_SAFE_END(f) } @@ -245,6 +256,8 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, return NULL; } else { + assert(numfree > 0); + --numfree; f = free_list; free_list = free_list->f_back; if (f->ob_size < extras) { @@ -475,5 +488,7 @@ PyFrame_Fini(void) PyFrameObject *f = free_list; free_list = free_list->f_back; PyObject_GC_Del(f); + --numfree; } + assert(numfree == 0); }