diff options
author | Tim Peters <tim.peters@gmail.com> | 2002-04-13 05:21:47 +0000 |
---|---|---|
committer | Tim Peters <tim.peters@gmail.com> | 2002-04-13 05:21:47 +0000 |
commit | b7ba7433126bff12dd638f11f831fa7bfd0bbf4a (patch) | |
tree | 951236002d7aa39e824b9d165e89dc8f0292e7b4 /Objects/frameobject.c | |
parent | Document the optional argument to the .strip(), .rstrip(), .strip() string (diff) | |
download | cpython-b7ba7433126bff12dd638f11f831fa7bfd0bbf4a.tar.gz cpython-b7ba7433126bff12dd638f11f831fa7bfd0bbf4a.tar.bz2 cpython-b7ba7433126bff12dd638f11f831fa7bfd0bbf4a.zip |
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).
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r-- | Objects/frameobject.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 8e4c60ff272..165121d8f87 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); } |