@@ -70,6 +70,7 @@ PG_MODULE_MAGIC;
7070 *
7171 * The plperl_interp_desc structs are kept in a Postgres hash table indexed
7272 * by userid OID, with OID 0 used for the single untrusted interpreter.
73+ * Once created, an interpreter is kept for the life of the process.
7374 *
7475 * We start out by creating a "held" interpreter, which we initialize
7576 * only as far as we can do without deciding if it will be trusted or
@@ -95,28 +96,44 @@ typedef struct plperl_interp_desc
9596
9697/**********************************************************************
9798 * The information we cache about loaded procedures
99+ *
100+ * The refcount field counts the struct's reference from the hash table shown
101+ * below, plus one reference for each function call level that is using the
102+ * struct. We can release the struct, and the associated Perl sub, when the
103+ * refcount goes to zero.
98104 **********************************************************************/
99105typedef struct plperl_proc_desc
100106{
101107char * proname ;/* user name of procedure */
102- TransactionId fn_xmin ;
108+ TransactionId fn_xmin ;/* xmin/TID of procedure's pg_proc tuple */
103109ItemPointerData fn_tid ;
110+ int refcount ;/* reference count of this struct */
111+ SV * reference ;/* CODE reference for Perl sub */
104112plperl_interp_desc * interp ;/* interpreter it's created in */
105- bool fn_readonly ;
106- bool lanpltrusted ;
113+ bool fn_readonly ;/* is function readonly (not volatile)? */
114+ bool lanpltrusted ;/* is it plperl, rather than plperlu? */
107115bool fn_retistuple ;/* true, if function returns tuple */
108116bool fn_retisset ;/* true, if function returns set */
109117bool fn_retisarray ;/* true if function returns array */
118+ /* Conversion info for function's result type: */
110119Oid result_oid ;/* Oid of result type */
111120FmgrInfo result_in_func ;/* I/O function and arg for result type */
112121Oid result_typioparam ;
122+ /* Conversion info for function's argument types: */
113123int nargs ;
114124FmgrInfo arg_out_func [FUNC_MAX_ARGS ];
115125bool arg_is_rowtype [FUNC_MAX_ARGS ];
116126Oid arg_arraytype [FUNC_MAX_ARGS ];/* InvalidOid if not an array */
117- SV * reference ;
118127}plperl_proc_desc ;
119128
129+ #define increment_prodesc_refcount (prodesc ) \
130+ ((prodesc)->refcount++)
131+ #define decrement_prodesc_refcount (prodesc ) \
132+ do { \
133+ if (--((prodesc)->refcount) <= 0) \
134+ free_plperl_function(prodesc); \
135+ } while(0)
136+
120137/**********************************************************************
121138 * For speedy lookup, we maintain a hash table mapping from
122139 * function OID + trigger flag + user OID to plperl_proc_desc pointers.
@@ -238,6 +255,8 @@ static void set_interp_require(bool trusted);
238255static Datum plperl_func_handler (PG_FUNCTION_ARGS );
239256static Datum plperl_trigger_handler (PG_FUNCTION_ARGS );
240257
258+ static void free_plperl_function (plperl_proc_desc * prodesc );
259+
241260static plperl_proc_desc * compile_plperl_function (Oid fn_oid ,bool is_trigger );
242261
243262static SV * plperl_hash_from_tuple (HeapTuple tuple ,TupleDesc tupdesc );
@@ -1689,19 +1708,24 @@ plperl_call_handler(PG_FUNCTION_ARGS)
16891708
16901709PG_TRY ();
16911710{
1711+ current_call_data = NULL ;
16921712if (CALLED_AS_TRIGGER (fcinfo ))
16931713retval = PointerGetDatum (plperl_trigger_handler (fcinfo ));
16941714else
16951715retval = plperl_func_handler (fcinfo );
16961716}
16971717PG_CATCH ();
16981718{
1719+ if (current_call_data && current_call_data -> prodesc )
1720+ decrement_prodesc_refcount (current_call_data -> prodesc );
16991721current_call_data = save_call_data ;
17001722activate_interpreter (oldinterp );
17011723PG_RE_THROW ();
17021724}
17031725PG_END_TRY ();
17041726
1727+ if (current_call_data && current_call_data -> prodesc )
1728+ decrement_prodesc_refcount (current_call_data -> prodesc );
17051729current_call_data = save_call_data ;
17061730activate_interpreter (oldinterp );
17071731return retval ;
@@ -1753,14 +1777,15 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
17531777desc .nargs = 0 ;
17541778desc .reference = NULL ;
17551779
1756- current_call_data = (plperl_call_data * )palloc0 (sizeof (plperl_call_data ));
1757- current_call_data -> fcinfo = & fake_fcinfo ;
1758- current_call_data -> prodesc = & desc ;
1759-
17601780PG_TRY ();
17611781{
17621782SV * perlret ;
17631783
1784+ current_call_data = (plperl_call_data * )palloc0 (sizeof (plperl_call_data ));
1785+ current_call_data -> fcinfo = & fake_fcinfo ;
1786+ current_call_data -> prodesc = & desc ;
1787+ /* we do not bother with refcounting the fake prodesc */
1788+
17641789if (SPI_connect ()!= SPI_OK_CONNECT )
17651790elog (ERROR ,"could not connect to SPI manager" );
17661791
@@ -2154,6 +2179,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
21542179
21552180prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false);
21562181current_call_data -> prodesc = prodesc ;
2182+ increment_prodesc_refcount (prodesc );
21572183
21582184/* Set a callback for error reporting */
21592185pl_error_context .callback = plperl_exec_callback ;
@@ -2274,6 +2300,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
22742300/* Find or compile the function */
22752301prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , true);
22762302current_call_data -> prodesc = prodesc ;
2303+ increment_prodesc_refcount (prodesc );
22772304
22782305/* Set a callback for error reporting */
22792306pl_error_context .callback = plperl_exec_callback ;
@@ -2383,23 +2410,35 @@ validate_plperl_function(plperl_proc_ptr *proc_ptr, HeapTuple procTup)
23832410
23842411/* Otherwise, unlink the obsoleted entry from the hashtable ... */
23852412proc_ptr -> proc_ptr = NULL ;
2386- /* ... and throw it away */
2387- if (prodesc -> reference )
2388- {
2389- plperl_interp_desc * oldinterp = plperl_active_interp ;
2390-
2391- activate_interpreter (prodesc -> interp );
2392- SvREFCNT_dec (prodesc -> reference );
2393- activate_interpreter (oldinterp );
2394- }
2395- free (prodesc -> proname );
2396- free (prodesc );
2413+ /* ... and release the corresponding refcount, probably deleting it */
2414+ decrement_prodesc_refcount (prodesc );
23972415}
23982416
23992417return false;
24002418}
24012419
24022420
2421+ static void
2422+ free_plperl_function (plperl_proc_desc * prodesc )
2423+ {
2424+ Assert (prodesc -> refcount <=0 );
2425+ /* Release CODE reference, if we have one, from the appropriate interp */
2426+ if (prodesc -> reference )
2427+ {
2428+ plperl_interp_desc * oldinterp = plperl_active_interp ;
2429+
2430+ activate_interpreter (prodesc -> interp );
2431+ SvREFCNT_dec (prodesc -> reference );
2432+ activate_interpreter (oldinterp );
2433+ }
2434+ /* Get rid of what we conveniently can of our own structs */
2435+ /* (FmgrInfo subsidiary info will get leaked ...) */
2436+ if (prodesc -> proname )
2437+ free (prodesc -> proname );
2438+ free (prodesc );
2439+ }
2440+
2441+
24032442static plperl_proc_desc *
24042443compile_plperl_function (Oid fn_oid ,bool is_trigger )
24052444{
@@ -2470,12 +2509,17 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
24702509ereport (ERROR ,
24712510(errcode (ERRCODE_OUT_OF_MEMORY ),
24722511errmsg ("out of memory" )));
2512+ /* Initialize all fields to 0 so free_plperl_function is safe */
24732513MemSet (prodesc ,0 ,sizeof (plperl_proc_desc ));
2514+
24742515prodesc -> proname = strdup (NameStr (procStruct -> proname ));
24752516if (prodesc -> proname == NULL )
2517+ {
2518+ free_plperl_function (prodesc );
24762519ereport (ERROR ,
24772520(errcode (ERRCODE_OUT_OF_MEMORY ),
24782521errmsg ("out of memory" )));
2522+ }
24792523prodesc -> fn_xmin = HeapTupleHeaderGetXmin (procTup -> t_data );
24802524prodesc -> fn_tid = procTup -> t_self ;
24812525
@@ -2490,8 +2534,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
24902534ObjectIdGetDatum (procStruct -> prolang ));
24912535if (!HeapTupleIsValid (langTup ))
24922536{
2493- free (prodesc -> proname );
2494- free (prodesc );
2537+ free_plperl_function (prodesc );
24952538elog (ERROR ,"cache lookup failed for language %u" ,
24962539procStruct -> prolang );
24972540}
@@ -2510,8 +2553,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25102553ObjectIdGetDatum (procStruct -> prorettype ));
25112554if (!HeapTupleIsValid (typeTup ))
25122555{
2513- free (prodesc -> proname );
2514- free (prodesc );
2556+ free_plperl_function (prodesc );
25152557elog (ERROR ,"cache lookup failed for type %u" ,
25162558procStruct -> prorettype );
25172559}
@@ -2525,17 +2567,15 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25252567/* okay */ ;
25262568else if (procStruct -> prorettype == TRIGGEROID )
25272569{
2528- free (prodesc -> proname );
2529- free (prodesc );
2570+ free_plperl_function (prodesc );
25302571ereport (ERROR ,
25312572(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25322573errmsg ("trigger functions can only be called "
25332574"as triggers" )));
25342575}
25352576else
25362577{
2537- free (prodesc -> proname );
2538- free (prodesc );
2578+ free_plperl_function (prodesc );
25392579ereport (ERROR ,
25402580(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25412581errmsg ("PL/Perl functions cannot return type %s" ,
@@ -2570,8 +2610,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25702610ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
25712611if (!HeapTupleIsValid (typeTup ))
25722612{
2573- free (prodesc -> proname );
2574- free (prodesc );
2613+ free_plperl_function (prodesc );
25752614elog (ERROR ,"cache lookup failed for type %u" ,
25762615procStruct -> proargtypes .values [i ]);
25772616}
@@ -2581,8 +2620,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25812620if (typeStruct -> typtype == TYPTYPE_PSEUDO &&
25822621procStruct -> proargtypes .values [i ]!= RECORDOID )
25832622{
2584- free (prodesc -> proname );
2585- free (prodesc );
2623+ free_plperl_function (prodesc );
25862624ereport (ERROR ,
25872625(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25882626errmsg ("PL/Perl functions cannot accept type %s" ,
@@ -2635,8 +2673,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
26352673pfree (proc_source );
26362674if (!prodesc -> reference )/* can this happen? */
26372675{
2638- free (prodesc -> proname );
2639- free (prodesc );
2676+ free_plperl_function (prodesc );
26402677elog (ERROR ,"could not create PL/Perl internal procedure" );
26412678}
26422679
@@ -2648,6 +2685,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
26482685proc_ptr = hash_search (plperl_proc_hash ,& proc_key ,
26492686HASH_ENTER ,NULL );
26502687proc_ptr -> proc_ptr = prodesc ;
2688+ increment_prodesc_refcount (prodesc );
26512689}
26522690
26532691/* restore previous error callback */