Index: src/backend/utils/fmgr/funcapi.c =================================================================== RCS file: /opt/src/cvs/pgsql-server/src/backend/utils/fmgr/funcapi.c,v retrieving revision 1.12 diff -c -r1.12 funcapi.c *** src/backend/utils/fmgr/funcapi.c 29 Nov 2003 19:52:01 -0000 1.12 --- src/backend/utils/fmgr/funcapi.c 19 Dec 2003 00:01:46 -0000 *************** *** 17,22 **** --- 17,23 ---- #include "catalog/pg_type.h" #include "utils/syscache.h" + static void shutdown_MultiFuncCall(Datum arg); /* * init_MultiFuncCall *************** *** 41,47 **** { /* * First call ! * * Allocate suitably long-lived space and zero it */ retval = (FuncCallContext *) --- 42,51 ---- { /* * First call ! */ ! ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo; ! ! /* * Allocate suitably long-lived space and zero it */ retval = (FuncCallContext *) *************** *** 63,68 **** --- 67,80 ---- * save the pointer for cross-call use */ fcinfo->flinfo->fn_extra = retval; + + /* + * Ensure we will get shut down cleanly if the exprcontext is not + * run to completion. + */ + RegisterExprContextCallback(rsi->econtext, + shutdown_MultiFuncCall, + PointerGetDatum(fcinfo->flinfo)); } else { *************** *** 108,115 **** void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx) { ! /* unbind from fcinfo */ ! fcinfo->flinfo->fn_extra = NULL; /* * Caller is responsible to free up memory for individual struct --- 120,148 ---- void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx) { ! ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo; ! ! /* Deregister the shutdown callback */ ! UnregisterExprContextCallback(rsi->econtext, ! shutdown_MultiFuncCall, ! PointerGetDatum(fcinfo->flinfo)); ! ! /* But use it to do the real work */ ! shutdown_MultiFuncCall(PointerGetDatum(fcinfo->flinfo)); ! } ! ! /* ! * shutdown_MultiFuncCall ! * Shutdown function to clean up after init_MultiFuncCall ! */ ! static void ! shutdown_MultiFuncCall(Datum arg) ! { ! FmgrInfo *flinfo = (FmgrInfo *) DatumGetPointer(arg); ! FuncCallContext *funcctx = (FuncCallContext *) flinfo->fn_extra; ! ! /* unbind from flinfo */ ! flinfo->fn_extra = NULL; /* * Caller is responsible to free up memory for individual struct