From 61f46abd4509cc519de3e43adfd9e0b4fa0f6fcb Mon Sep 17 00:00:00 2001 From: Matheus Alcantara 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)