embedding python 1.5.2 problem - Py_Finalize memory leaks

Warren Postma embed at NOSPAM.geocities.com
Wed Sep 13 09:22:47 EDT 2000


I need to be able to cleanly restart Python with ZERO leaked memory, because
I am running a low memory embedded system, and we need to determine low
memory conditions and perform a soft restart of python, in order to prevent
the embedded system running python from crashing. This is also our current
workaround for when a script like "while 1: pass" gets executed in a thread.
We need to kill the thread, but the only way to do so that seems feasible is
to shut down python and restart  it. Since our entire embedded system is but
a single task, and there are other non-python threads (written in C) which
are running critical system monitoring functions, we cannot just kill the
python executable and restart it.

I believe that I am cleaning Python 1.5.2 up to a point which has not
previously been attempted. In doing so I have run into a new problem.

For one thing, I am trying to rid Python 1.5.2 of memory leaks.   There are
a variety of leaks in Python, as reported by the heap checking functions of
Visual C++.   One of the most troubling is actually documented in the
Py_Finalize() function in pythonrun.c:

void
Py_Finalize()
{
....
 PyFloat_Fini();

 /* XXX Still allocated:
    - various static ad-hoc pointers to interned strings
    - int and float free list blocks
    - whatever various modules and libraries allocate
 */

}

So, in a misguided attempt to solve at least one of those problems, I tried
to clean up the "interned" strings dictionary, by adding this code to
stringobject.c and calling it as the last thing in Py_Finalize:

void PyString_DeleteInternedStrings(void)
{
    Py_DECREF(interned); // warren added
    interned=0x0; // warren added

};

Unfortunately, it appears that "interned" is not deleted on purpose, because
the following code, called indirectly through the Py_DECREF above, causes
memory heap corruption:

static void
dict_dealloc(mp)
 register dictobject *mp;
{
 register int i;
 register dictentry *ep;
 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
  if (ep->me_key != NULL) {
   Py_DECREF(ep->me_key); <- HERE
  }
  if (ep->me_value != NULL) {
   Py_DECREF(ep->me_value);
  }
 }
 PyMem_XDEL(mp->ma_table); <- HERE
 PyMem_DEL(mp);
}

The two lines above that appear to be deleting interned keyword strings
representing the types themselves, such as "string", and so on. What is
wrong here? What on earth is going on?

Has anyone ever "cleaned up" the Py_Finalize code in Python 1.5.2 to make
clean up all allocated memory nicely?

Warren







More information about the Python-list mailing list