I have attached the pltcl patch again, just in case. For the sake of clarity
authorBruce Momjian <[email protected]>
Thu, 26 Sep 2002 05:23:26 +0000 (05:23 +0000)
committerBruce Momjian <[email protected]>
Thu, 26 Sep 2002 05:23:26 +0000 (05:23 +0000)
let's say this patch superscedes the previous one.

I have also attached a patch addressing the similar memory leak problem in
plpython. This includes a slight adjustment of the tests in the source
directory. The patch also includes a cosmetic change to remove a compiler
warning although I think the change makes the code look worse though.

BTW, by my reckoning the memory leak would occur with prepared plans and
without. If that is not the case then I've been barking up the wrong tree.

Nigel J. Andrews

src/pl/plpython/feature.expected
src/pl/plpython/plpython.c
src/pl/plpython/plpython_schema.sql
src/pl/tcl/pltcl.c

index 9afd782e7d27644b62187d912707d590149f157c..b689c1f6154994c1a667aab9a915f221d9205aac 100644 (file)
@@ -29,7 +29,7 @@ SELECT global_test_two();
 (1 row)
 
 SELECT import_fail();
-WARNING:  ('import socket failed -- untrusted dynamic module: _socket',)
+NOTICE:  ('import socket failed -- untrusted dynamic module: _socket',)
     import_fail     
 --------------------
  failed as expected
index 33013b165a3ddcd742c428dba3982bb3c67594bd..001f54fda745adcdf8ee3126fb172e223f64cf87 100644 (file)
@@ -408,7 +408,9 @@ plpython_call_handler(PG_FUNCTION_ARGS)
                else
                        PLy_restart_in_progress += 1;
                if (proc)
+               {
                        Py_DECREF(proc->me);
+               }
                RERAISE_EXC();
        }
 
@@ -1841,7 +1843,14 @@ PLy_plan_dealloc(PyObject * arg)
                 *
                 * FIXME -- leaks saved plan on object destruction.  can this be
                 * avoided?
+                * I think so. A function prepares and then execp's a statement.
+                * When we come to deallocate the 'statement' object we obviously
+                * no long need the plan. Even if we did, without the object
+                * we're never going to be able to use it again.
+                * In the against arguments: SPI_saveplan has stuck this under
+                * the top context so there must be a reason for doing that.
                 */
+               pfree(ob->plan);
        }
        if (ob->types)
                PLy_free(ob->types);
@@ -2374,6 +2383,8 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, int rows, int status)
                                PyList_SetItem(result->rows, i, row);
                        }
                        PLy_typeinfo_dealloc(&args);
+
+                       SPI_freetuptable(tuptable);
                }
                RESTORE_EXC();
        }
index 28ceef55350ccfc7d63a199259df116bc8ae83b9..2f8766431fae803ff9c2b0a8ea491f75b832cb8c 100644 (file)
@@ -20,7 +20,7 @@ CREATE TABLE taxonomy (
 
 CREATE TABLE entry (
        accession text not null primary key,
-       eid serial,
+       eid serial unique,
        txid int2 not null references taxonomy(id)
        ) ;
 
index bbcaa974b83f00a8fb950ac1d8266519e5f38a97..58c9bd3d5dbe643d163783f03237f28afb33235b 100644 (file)
@@ -1647,6 +1647,7 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
                        pltcl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);
                sprintf(buf, "%d", ntuples);
                Tcl_SetResult(interp, buf, TCL_VOLATILE);
+               SPI_freetuptable(SPI_tuptable);
                memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
                return TCL_OK;
        }
@@ -1668,15 +1669,19 @@ pltcl_SPI_exec(ClientData cdata, Tcl_Interp *interp,
                        continue;
                if (loop_rc == TCL_RETURN)
                {
+                       SPI_freetuptable(SPI_tuptable);
                        memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
                        return TCL_RETURN;
                }
                if (loop_rc == TCL_BREAK)
                        break;
+               SPI_freetuptable(SPI_tuptable);
                memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
                return TCL_ERROR;
        }
 
+       SPI_freetuptable(SPI_tuptable);
+
        /************************************************************
         * Finally return the number of tuples
         ************************************************************/
@@ -2207,6 +2212,7 @@ pltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
        {
                if (ntuples > 0)
                        pltcl_set_tuple_values(interp, arrayname, 0, tuples[0], tupdesc);
+               SPI_freetuptable(SPI_tuptable);
                memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
                sprintf(buf, "%d", ntuples);
                Tcl_SetResult(interp, buf, TCL_VOLATILE);
@@ -2229,15 +2235,19 @@ pltcl_SPI_execp(ClientData cdata, Tcl_Interp *interp,
                        continue;
                if (loop_rc == TCL_RETURN)
                {
+                       SPI_freetuptable(SPI_tuptable);
                        memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
                        return TCL_RETURN;
                }
                if (loop_rc == TCL_BREAK)
                        break;
+               SPI_freetuptable(SPI_tuptable);
                memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
                return TCL_ERROR;
        }
 
+       SPI_freetuptable(SPI_tuptable);
+
        /************************************************************
         * Finally return the number of tuples
         ************************************************************/