Hi all,

plpython[u] leaks memory in PLy_spi_execute_fetch_result in the following 
snippet: 

Py_DECREF(result->nrows);
result->nrows = PyInt_FromLong(rows);
PLy_typeinfo_init(&args);

oldcontext = CurrentMemoryContext;
PG_TRY();
{
        if (rows)
        {
                Py_DECREF(result->rows);
                result->rows = PyList_New(rows);

                PLy_input_tuple_funcs(&args, tuptable->tupdesc);
                for (i = 0; i < rows; i++)
                {
                        PyObject   *row = PLyDict_FromTuple(&args, 
tuptable->vals[i],
                                                                                
          tuptable->tupdesc);

                        PyList_SetItem(result->rows, i, row);
                }
                PLy_typeinfo_dealloc(&args);

                SPI_freetuptable(tuptable);
        }
}
PG_CATCH();
{
        MemoryContextSwitchTo(oldcontext);
        PLy_error_in_progress = CopyErrorData();
        FlushErrorState();
        if (!PyErr_Occurred())
                PyErr_SetString(PLy_exc_error,
                                "Unknown error in 
PLy_spi_execute_fetch_result");
        Py_DECREF(result);
        PLy_typeinfo_dealloc(&args);
        return NULL;
}
PG_END_TRY();

if rows is 0 PLy_typeinfo_dealloc and SPI_freetuptable will not be called. An 
easy example where this is easily leading to a fast growing memleak (1G in 
5s):

DO LANGUAGE 'plpythonu' $$while True: plpy.execute("SELECT 1 WHERE false")$$;


The fix is simple. Just move those two outside the if block. As a slightly 
alternative solution one could also remove the "return NULL" and move those 
outside the PG_CATCH.

Found when investigating a problem of 'bag' on irc (bcc'ed, he had to go home 
before I though of asking him whether its ok to publish his name/mail).

Andres

-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Reply via email to