]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
SF bug 543148: Memory leak with stackframes + inspect.
authorTim Peters <tim.peters@gmail.com>
Sat, 13 Apr 2002 05:25:28 +0000 (05:25 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 13 Apr 2002 05:25:28 +0000 (05:25 +0000)
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).

Misc/NEWS
Objects/frameobject.c

index 09b68097c775e1db4caaf716f5b25d5555efb4ad..6411be870fc09eb047d71490dcead53a9bfd677a 100644 (file)
--- 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
 =================================
index 8e4c60ff2722a2af20498998122e8c981544b71e..165121d8f8715505ff3254e28a9fd23136438c95 100644 (file)
@@ -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);
 }