plpython-tuple-to-dict-leak.patch
text/x-diff
Filename: plpython-tuple-to-dict-leak.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/pl/plpython/plpy_main.c | 0 | 0 |
| src/pl/plpython/plpy_procedure.c | 0 | 0 |
| src/pl/plpython/plpy_procedure.h | 0 | 0 |
| src/pl/plpython/plpy_typeio.c | 0 | 0 |
diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
index ae9d87e..79d7784 100644
*** a/src/pl/plpython/plpy_main.c
--- b/src/pl/plpython/plpy_main.c
***************
*** 12,17 ****
--- 12,18 ----
#include "executor/spi.h"
#include "miscadmin.h"
#include "utils/guc.h"
+ #include "utils/memutils.h"
#include "utils/syscache.h"
#include "plpython.h"
*************** plpython_inline_handler(PG_FUNCTION_ARGS
*** 268,273 ****
--- 269,279 ----
MemSet(&proc, 0, sizeof(PLyProcedure));
proc.pyname = PLy_strdup("__plpython_inline_block");
+ proc.tmp_ctx = AllocSetContextCreate(TopMemoryContext,
+ "PL/Python temporary ctx",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
proc.result.out.d.typoid = VOIDOID;
PG_TRY();
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index 229966a..f539cec 100644
*** a/src/pl/plpython/plpy_procedure.c
--- b/src/pl/plpython/plpy_procedure.c
***************
*** 12,17 ****
--- 12,18 ----
#include "catalog/pg_type.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
+ #include "utils/memutils.h"
#include "utils/syscache.h"
#include "plpython.h"
*************** PLy_procedure_create(HeapTuple procTup,
*** 169,174 ****
--- 170,180 ----
proc->setof = NULL;
proc->src = NULL;
proc->argnames = NULL;
+ proc->tmp_ctx = AllocSetContextCreate(TopMemoryContext,
+ "PL/Python temporary ctx",
+ ALLOCSET_DEFAULT_MINSIZE,
+ ALLOCSET_DEFAULT_INITSIZE,
+ ALLOCSET_DEFAULT_MAXSIZE);
PG_TRY();
{
*************** PLy_procedure_delete(PLyProcedure *proc)
*** 411,416 ****
--- 417,424 ----
PLy_free(proc->src);
if (proc->argnames)
PLy_free(proc->argnames);
+ if (proc->tmp_ctx)
+ MemoryContextDelete(proc->tmp_ctx);
}
/*
diff --git a/src/pl/plpython/plpy_procedure.h b/src/pl/plpython/plpy_procedure.h
index e986c7e..5ee73fa 100644
*** a/src/pl/plpython/plpy_procedure.h
--- b/src/pl/plpython/plpy_procedure.h
*************** typedef struct PLyProcedure
*** 30,35 ****
--- 30,36 ----
PyObject *code; /* compiled procedure code */
PyObject *statics; /* data saved across calls, local scope */
PyObject *globals; /* data saved across calls, global scope */
+ MemoryContext tmp_ctx;
} PLyProcedure;
/* the procedure cache entry */
diff --git a/src/pl/plpython/plpy_typeio.c b/src/pl/plpython/plpy_typeio.c
index d5cac9f..6f0eb46 100644
*** a/src/pl/plpython/plpy_typeio.c
--- b/src/pl/plpython/plpy_typeio.c
***************
*** 23,28 ****
--- 23,29 ----
#include "plpy_typeio.h"
#include "plpy_elog.h"
+ #include "plpy_procedure.h"
/* I/O function caching */
*************** PLy_output_record_funcs(PLyTypeInfo *arg
*** 258,268 ****
Assert(arg->is_rowtype == 1);
}
PyObject *
PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
{
! PyObject *volatile dict;
! int i;
if (info->is_rowtype != 1)
elog(ERROR, "PLyTypeInfo structure describes a datum");
--- 259,274 ----
Assert(arg->is_rowtype == 1);
}
+ /*
+ * Transform a tuple into a Python dict object. The transformation can result
+ * in memory allocation, so it's done in a scratch memory context.
+ */
PyObject *
PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
{
! PyObject *volatile dict;
! MemoryContext oldcontext;
! int i;
if (info->is_rowtype != 1)
elog(ERROR, "PLyTypeInfo structure describes a datum");
*************** PLyDict_FromTuple(PLyTypeInfo *info, Hea
*** 271,276 ****
--- 277,284 ----
if (dict == NULL)
PLy_elog(ERROR, "could not create new dictionary");
+ oldcontext = MemoryContextSwitchTo(PLy_curr_procedure->tmp_ctx);
+
PG_TRY();
{
for (i = 0; i < info->in.r.natts; i++)
*************** PLyDict_FromTuple(PLyTypeInfo *info, Hea
*** 298,308 ****
--- 306,322 ----
}
PG_CATCH();
{
+ MemoryContextSwitchTo(oldcontext);
+ MemoryContextReset(PLy_curr_procedure->tmp_ctx);
+
Py_DECREF(dict);
PG_RE_THROW();
}
PG_END_TRY();
+ MemoryContextSwitchTo(oldcontext);
+ MemoryContextReset(PLy_curr_procedure->tmp_ctx);
+
return dict;
}