Hi!
I have tested the proposed patch and it works nicely. Let me know if
further testing is necessary or if i can help.
Thanks!
Björn
Am Freitag, den 30.04.2010, 01:14 +0200 schrieb Andres Freund:
> 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,
> "iso-8859-1 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
--
Björn Grüning
Albert-Ludwigs-Universität Freiburg
Institut für Pharmazeutische Wissenschaften
Pharmazeutische Bioinformatik
Hermann-Herder-Strasse 9
D-79104 Freiburg i. Br.
Tel.: +49-761-203-4872
E-Mail: bjoern.gruening@pharmazie.uni-freiburg.de