0001-plpython-Use-correct-memory-context-for-savedargs.patch
text/plain
Filename: 0001-plpython-Use-correct-memory-context-for-savedargs.patch
Type: text/plain
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: format-patch
Series: patch 0001
Subject: plpython: Use correct memory context for savedargs
| File | + | − |
|---|---|---|
| src/pl/plpython/plpy_exec.c | 20 | 7 |
From 61f46abd4509cc519de3e43adfd9e0b4fa0f6fcb Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <mths.dev@pm.me>
Date: Mon, 25 May 2026 19:22:09 -0300
Subject: [PATCH] plpython: Use correct memory context for savedargs
---
src/pl/plpython/plpy_exec.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index de0dad1f533..d93e800e0be 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -31,7 +31,7 @@ typedef struct PLySRFState
} PLySRFState;
static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc);
-static PLySavedArgs *PLy_function_save_args(PLyProcedure *proc);
+static PLySavedArgs *PLy_function_save_args(MemoryContext mctx, PLyProcedure *proc);
static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs);
static void PLy_function_drop_args(PLySavedArgs *savedargs);
static void PLy_global_args_push(PLyProcedure *proc);
@@ -176,8 +176,15 @@ PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
* This won't be last call, so save argument values. We do
* this again each time in case the iterator is changing those
* values.
+ *
+ * We use funcctx->multi_call_memory_ctx to ensure savedargs
+ * survives across ValuePerCall invocations, but is cleaned up
+ * when the SRF completes. This also protects against the
+ * case where the procedure is delated (via
+ * PLy_procedure_delete ) while the SRF is running.
*/
- srfstate->savedargs = PLy_function_save_args(proc);
+ srfstate->savedargs = PLy_function_save_args(funcctx->multi_call_memory_ctx,
+ proc);
}
}
@@ -536,13 +543,13 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
* available via the proc's globals :-( ... but we're stuck with that now.
*/
static PLySavedArgs *
-PLy_function_save_args(PLyProcedure *proc)
+PLy_function_save_args(MemoryContext mctx, PLyProcedure *proc)
{
PLySavedArgs *result;
- /* saved args are always allocated in procedure's context */
+ /* Allocate in the caller-specified memory context */
result = (PLySavedArgs *)
- MemoryContextAllocZero(proc->mcxt,
+ MemoryContextAllocZero(mctx,
offsetof(PLySavedArgs, namedargs) +
proc->nargs * sizeof(PyObject *));
result->nargs = proc->nargs;
@@ -658,8 +665,14 @@ PLy_global_args_push(PLyProcedure *proc)
{
PLySavedArgs *node;
- /* Build a struct containing current argument values */
- node = PLy_function_save_args(proc);
+ /*
+ * Build a struct containing current argument values. We use
+ * proc->mcxt because the saved args must persist across the entire
+ * recursive call stack, which can span multiple function invocations.
+ * The procedure's memory context has the appropriate lifetime for
+ * this, and we explicitly free the struct when popping.
+ */
+ node = PLy_function_save_args(proc->mcxt, proc);
/*
* Push the saved argument values into the procedure's stack. Once we
--
2.50.1 (Apple Git-155)