@@ -68,6 +68,7 @@ PG_MODULE_MAGIC;
6868 *
6969 * The plperl_interp_desc structs are kept in a Postgres hash table indexed
7070 * by userid OID, with OID 0 used for the single untrusted interpreter.
71+ * Once created, an interpreter is kept for the life of the process.
7172 *
7273 * We start out by creating a "held" interpreter, which we initialize
7374 * only as far as we can do without deciding if it will be trusted or
@@ -93,28 +94,44 @@ typedef struct plperl_interp_desc
9394
9495/**********************************************************************
9596 * The information we cache about loaded procedures
97+ *
98+ * The refcount field counts the struct's reference from the hash table shown
99+ * below, plus one reference for each function call level that is using the
100+ * struct. We can release the struct, and the associated Perl sub, when the
101+ * refcount goes to zero.
96102 **********************************************************************/
97103typedef struct plperl_proc_desc
98104{
99105char * proname ;/* user name of procedure */
100- TransactionId fn_xmin ;
106+ TransactionId fn_xmin ;/* xmin/TID of procedure's pg_proc tuple */
101107ItemPointerData fn_tid ;
108+ int refcount ;/* reference count of this struct */
109+ SV * reference ;/* CODE reference for Perl sub */
102110plperl_interp_desc * interp ;/* interpreter it's created in */
103- bool fn_readonly ;
104- bool lanpltrusted ;
111+ bool fn_readonly ;/* is function readonly (not volatile)? */
112+ bool lanpltrusted ;/* is it plperl, rather than plperlu? */
105113bool fn_retistuple ;/* true, if function returns tuple */
106114bool fn_retisset ;/* true, if function returns set */
107115bool fn_retisarray ;/* true if function returns array */
116+ /* Conversion info for function's result type: */
108117Oid result_oid ;/* Oid of result type */
109118FmgrInfo result_in_func ;/* I/O function and arg for result type */
110119Oid result_typioparam ;
120+ /* Conversion info for function's argument types: */
111121int nargs ;
112122FmgrInfo arg_out_func [FUNC_MAX_ARGS ];
113123bool arg_is_rowtype [FUNC_MAX_ARGS ];
114124Oid arg_arraytype [FUNC_MAX_ARGS ];/* InvalidOid if not an array */
115- SV * reference ;
116125}plperl_proc_desc ;
117126
127+ #define increment_prodesc_refcount (prodesc ) \
128+ ((prodesc)->refcount++)
129+ #define decrement_prodesc_refcount (prodesc ) \
130+ do { \
131+ if (--((prodesc)->refcount) <= 0) \
132+ free_plperl_function(prodesc); \
133+ } while(0)
134+
118135/**********************************************************************
119136 * For speedy lookup, we maintain a hash table mapping from
120137 * function OID + trigger flag + user OID to plperl_proc_desc pointers.
@@ -236,6 +253,8 @@ static void set_interp_require(bool trusted);
236253static Datum plperl_func_handler (PG_FUNCTION_ARGS );
237254static Datum plperl_trigger_handler (PG_FUNCTION_ARGS );
238255
256+ static void free_plperl_function (plperl_proc_desc * prodesc );
257+
239258static plperl_proc_desc * compile_plperl_function (Oid fn_oid ,bool is_trigger );
240259
241260static SV * plperl_hash_from_tuple (HeapTuple tuple ,TupleDesc tupdesc );
@@ -1679,19 +1698,24 @@ plperl_call_handler(PG_FUNCTION_ARGS)
16791698
16801699PG_TRY ();
16811700{
1701+ current_call_data = NULL ;
16821702if (CALLED_AS_TRIGGER (fcinfo ))
16831703retval = PointerGetDatum (plperl_trigger_handler (fcinfo ));
16841704else
16851705retval = plperl_func_handler (fcinfo );
16861706}
16871707PG_CATCH ();
16881708{
1709+ if (current_call_data && current_call_data -> prodesc )
1710+ decrement_prodesc_refcount (current_call_data -> prodesc );
16891711current_call_data = save_call_data ;
16901712activate_interpreter (oldinterp );
16911713PG_RE_THROW ();
16921714}
16931715PG_END_TRY ();
16941716
1717+ if (current_call_data && current_call_data -> prodesc )
1718+ decrement_prodesc_refcount (current_call_data -> prodesc );
16951719current_call_data = save_call_data ;
16961720activate_interpreter (oldinterp );
16971721return retval ;
@@ -1743,14 +1767,15 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
17431767desc .nargs = 0 ;
17441768desc .reference = NULL ;
17451769
1746- current_call_data = (plperl_call_data * )palloc0 (sizeof (plperl_call_data ));
1747- current_call_data -> fcinfo = & fake_fcinfo ;
1748- current_call_data -> prodesc = & desc ;
1749-
17501770PG_TRY ();
17511771{
17521772SV * perlret ;
17531773
1774+ current_call_data = (plperl_call_data * )palloc0 (sizeof (plperl_call_data ));
1775+ current_call_data -> fcinfo = & fake_fcinfo ;
1776+ current_call_data -> prodesc = & desc ;
1777+ /* we do not bother with refcounting the fake prodesc */
1778+
17541779if (SPI_connect ()!= SPI_OK_CONNECT )
17551780elog (ERROR ,"could not connect to SPI manager" );
17561781
@@ -2144,6 +2169,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
21442169
21452170prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false);
21462171current_call_data -> prodesc = prodesc ;
2172+ increment_prodesc_refcount (prodesc );
21472173
21482174/* Set a callback for error reporting */
21492175pl_error_context .callback = plperl_exec_callback ;
@@ -2264,6 +2290,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
22642290/* Find or compile the function */
22652291prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , true);
22662292current_call_data -> prodesc = prodesc ;
2293+ increment_prodesc_refcount (prodesc );
22672294
22682295/* Set a callback for error reporting */
22692296pl_error_context .callback = plperl_exec_callback ;
@@ -2373,23 +2400,35 @@ validate_plperl_function(plperl_proc_ptr *proc_ptr, HeapTuple procTup)
23732400
23742401/* Otherwise, unlink the obsoleted entry from the hashtable ... */
23752402proc_ptr -> proc_ptr = NULL ;
2376- /* ... and throw it away */
2377- if (prodesc -> reference )
2378- {
2379- plperl_interp_desc * oldinterp = plperl_active_interp ;
2380-
2381- activate_interpreter (prodesc -> interp );
2382- SvREFCNT_dec (prodesc -> reference );
2383- activate_interpreter (oldinterp );
2384- }
2385- free (prodesc -> proname );
2386- free (prodesc );
2403+ /* ... and release the corresponding refcount, probably deleting it */
2404+ decrement_prodesc_refcount (prodesc );
23872405}
23882406
23892407return false;
23902408}
23912409
23922410
2411+ static void
2412+ free_plperl_function (plperl_proc_desc * prodesc )
2413+ {
2414+ Assert (prodesc -> refcount <=0 );
2415+ /* Release CODE reference, if we have one, from the appropriate interp */
2416+ if (prodesc -> reference )
2417+ {
2418+ plperl_interp_desc * oldinterp = plperl_active_interp ;
2419+
2420+ activate_interpreter (prodesc -> interp );
2421+ SvREFCNT_dec (prodesc -> reference );
2422+ activate_interpreter (oldinterp );
2423+ }
2424+ /* Get rid of what we conveniently can of our own structs */
2425+ /* (FmgrInfo subsidiary info will get leaked ...) */
2426+ if (prodesc -> proname )
2427+ free (prodesc -> proname );
2428+ free (prodesc );
2429+ }
2430+
2431+
23932432static plperl_proc_desc *
23942433compile_plperl_function (Oid fn_oid ,bool is_trigger )
23952434{
@@ -2460,12 +2499,17 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
24602499ereport (ERROR ,
24612500(errcode (ERRCODE_OUT_OF_MEMORY ),
24622501errmsg ("out of memory" )));
2502+ /* Initialize all fields to 0 so free_plperl_function is safe */
24632503MemSet (prodesc ,0 ,sizeof (plperl_proc_desc ));
2504+
24642505prodesc -> proname = strdup (NameStr (procStruct -> proname ));
24652506if (prodesc -> proname == NULL )
2507+ {
2508+ free_plperl_function (prodesc );
24662509ereport (ERROR ,
24672510(errcode (ERRCODE_OUT_OF_MEMORY ),
24682511errmsg ("out of memory" )));
2512+ }
24692513prodesc -> fn_xmin = HeapTupleHeaderGetXmin (procTup -> t_data );
24702514prodesc -> fn_tid = procTup -> t_self ;
24712515
@@ -2480,8 +2524,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
24802524ObjectIdGetDatum (procStruct -> prolang ));
24812525if (!HeapTupleIsValid (langTup ))
24822526{
2483- free (prodesc -> proname );
2484- free (prodesc );
2527+ free_plperl_function (prodesc );
24852528elog (ERROR ,"cache lookup failed for language %u" ,
24862529procStruct -> prolang );
24872530}
@@ -2500,8 +2543,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25002543ObjectIdGetDatum (procStruct -> prorettype ));
25012544if (!HeapTupleIsValid (typeTup ))
25022545{
2503- free (prodesc -> proname );
2504- free (prodesc );
2546+ free_plperl_function (prodesc );
25052547elog (ERROR ,"cache lookup failed for type %u" ,
25062548procStruct -> prorettype );
25072549}
@@ -2515,17 +2557,15 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25152557/* okay */ ;
25162558else if (procStruct -> prorettype == TRIGGEROID )
25172559{
2518- free (prodesc -> proname );
2519- free (prodesc );
2560+ free_plperl_function (prodesc );
25202561ereport (ERROR ,
25212562(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25222563errmsg ("trigger functions can only be called "
25232564"as triggers" )));
25242565}
25252566else
25262567{
2527- free (prodesc -> proname );
2528- free (prodesc );
2568+ free_plperl_function (prodesc );
25292569ereport (ERROR ,
25302570(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25312571errmsg ("PL/Perl functions cannot return type %s" ,
@@ -2560,8 +2600,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25602600ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
25612601if (!HeapTupleIsValid (typeTup ))
25622602{
2563- free (prodesc -> proname );
2564- free (prodesc );
2603+ free_plperl_function (prodesc );
25652604elog (ERROR ,"cache lookup failed for type %u" ,
25662605procStruct -> proargtypes .values [i ]);
25672606}
@@ -2571,8 +2610,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25712610if (typeStruct -> typtype == TYPTYPE_PSEUDO &&
25722611procStruct -> proargtypes .values [i ]!= RECORDOID )
25732612{
2574- free (prodesc -> proname );
2575- free (prodesc );
2613+ free_plperl_function (prodesc );
25762614ereport (ERROR ,
25772615(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25782616errmsg ("PL/Perl functions cannot accept type %s" ,
@@ -2625,8 +2663,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
26252663pfree (proc_source );
26262664if (!prodesc -> reference )/* can this happen? */
26272665{
2628- free (prodesc -> proname );
2629- free (prodesc );
2666+ free_plperl_function (prodesc );
26302667elog (ERROR ,"could not create PL/Perl internal procedure" );
26312668}
26322669
@@ -2638,6 +2675,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
26382675proc_ptr = hash_search (plperl_proc_hash ,& proc_key ,
26392676HASH_ENTER ,NULL );
26402677proc_ptr -> proc_ptr = prodesc ;
2678+ increment_prodesc_refcount (prodesc );
26412679}
26422680
26432681/* restore previous error callback */