@@ -67,6 +67,7 @@ PG_MODULE_MAGIC;
6767 *
6868 * The plperl_interp_desc structs are kept in a Postgres hash table indexed
6969 * by userid OID, with OID 0 used for the single untrusted interpreter.
70+ * Once created, an interpreter is kept for the life of the process.
7071 *
7172 * We start out by creating a "held" interpreter, which we initialize
7273 * only as far as we can do without deciding if it will be trusted or
@@ -92,27 +93,43 @@ typedef struct plperl_interp_desc
9293
9394/**********************************************************************
9495 * The information we cache about loaded procedures
96+ *
97+ * The refcount field counts the struct's reference from the hash table shown
98+ * below, plus one reference for each function call level that is using the
99+ * struct. We can release the struct, and the associated Perl sub, when the
100+ * refcount goes to zero.
95101 **********************************************************************/
96102typedef struct plperl_proc_desc
97103{
98104char * proname ;/* user name of procedure */
99- TransactionId fn_xmin ;
105+ TransactionId fn_xmin ;/* xmin/TID of procedure's pg_proc tuple */
100106ItemPointerData fn_tid ;
107+ int refcount ;/* reference count of this struct */
108+ SV * reference ;/* CODE reference for Perl sub */
101109plperl_interp_desc * interp ;/* interpreter it's created in */
102- bool fn_readonly ;
103- bool lanpltrusted ;
110+ bool fn_readonly ;/* is function readonly (not volatile)? */
111+ bool lanpltrusted ;/* is it plperl, rather than plperlu? */
104112bool fn_retistuple ;/* true, if function returns tuple */
105113bool fn_retisset ;/* true, if function returns set */
106114bool fn_retisarray ;/* true if function returns array */
115+ /* Conversion info for function's result type: */
107116Oid result_oid ;/* Oid of result type */
108117FmgrInfo result_in_func ;/* I/O function and arg for result type */
109118Oid result_typioparam ;
119+ /* Conversion info for function's argument types: */
110120int nargs ;
111121FmgrInfo arg_out_func [FUNC_MAX_ARGS ];
112122bool arg_is_rowtype [FUNC_MAX_ARGS ];
113- SV * reference ;
114123}plperl_proc_desc ;
115124
125+ #define increment_prodesc_refcount (prodesc ) \
126+ ((prodesc)->refcount++)
127+ #define decrement_prodesc_refcount (prodesc ) \
128+ do { \
129+ if (--((prodesc)->refcount) <= 0) \
130+ free_plperl_function(prodesc); \
131+ } while(0)
132+
116133/**********************************************************************
117134 * For speedy lookup, we maintain a hash table mapping from
118135 * function OID + trigger flag + user OID to plperl_proc_desc pointers.
@@ -217,6 +234,8 @@ static void set_interp_require(bool trusted);
217234static Datum plperl_func_handler (PG_FUNCTION_ARGS );
218235static Datum plperl_trigger_handler (PG_FUNCTION_ARGS );
219236
237+ static void free_plperl_function (plperl_proc_desc * prodesc );
238+
220239static plperl_proc_desc * compile_plperl_function (Oid fn_oid ,bool is_trigger );
221240
222241static SV * plperl_hash_from_tuple (HeapTuple tuple ,TupleDesc tupdesc );
@@ -1228,19 +1247,24 @@ plperl_call_handler(PG_FUNCTION_ARGS)
12281247
12291248PG_TRY ();
12301249{
1250+ current_call_data = NULL ;
12311251if (CALLED_AS_TRIGGER (fcinfo ))
12321252retval = PointerGetDatum (plperl_trigger_handler (fcinfo ));
12331253else
12341254retval = plperl_func_handler (fcinfo );
12351255}
12361256PG_CATCH ();
12371257{
1258+ if (current_call_data && current_call_data -> prodesc )
1259+ decrement_prodesc_refcount (current_call_data -> prodesc );
12381260current_call_data = save_call_data ;
12391261activate_interpreter (oldinterp );
12401262PG_RE_THROW ();
12411263}
12421264PG_END_TRY ();
12431265
1266+ if (current_call_data && current_call_data -> prodesc )
1267+ decrement_prodesc_refcount (current_call_data -> prodesc );
12441268current_call_data = save_call_data ;
12451269activate_interpreter (oldinterp );
12461270return retval ;
@@ -1292,14 +1316,15 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
12921316desc .nargs = 0 ;
12931317desc .reference = NULL ;
12941318
1295- current_call_data = (plperl_call_data * )palloc0 (sizeof (plperl_call_data ));
1296- current_call_data -> fcinfo = & fake_fcinfo ;
1297- current_call_data -> prodesc = & desc ;
1298-
12991319PG_TRY ();
13001320{
13011321SV * perlret ;
13021322
1323+ current_call_data = (plperl_call_data * )palloc0 (sizeof (plperl_call_data ));
1324+ current_call_data -> fcinfo = & fake_fcinfo ;
1325+ current_call_data -> prodesc = & desc ;
1326+ /* we do not bother with refcounting the fake prodesc */
1327+
13031328if (SPI_connect ()!= SPI_OK_CONNECT )
13041329elog (ERROR ,"could not connect to SPI manager" );
13051330
@@ -1659,6 +1684,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
16591684
16601685prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false);
16611686current_call_data -> prodesc = prodesc ;
1687+ increment_prodesc_refcount (prodesc );
16621688
16631689/* Set a callback for error reporting */
16641690pl_error_context .callback = plperl_exec_callback ;
@@ -1820,6 +1846,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
18201846/* Find or compile the function */
18211847prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , true);
18221848current_call_data -> prodesc = prodesc ;
1849+ increment_prodesc_refcount (prodesc );
18231850
18241851/* Set a callback for error reporting */
18251852pl_error_context .callback = plperl_exec_callback ;
@@ -1928,23 +1955,35 @@ validate_plperl_function(plperl_proc_ptr *proc_ptr, HeapTuple procTup)
19281955
19291956/* Otherwise, unlink the obsoleted entry from the hashtable ... */
19301957proc_ptr -> proc_ptr = NULL ;
1931- /* ... and throw it away */
1932- if (prodesc -> reference )
1933- {
1934- plperl_interp_desc * oldinterp = plperl_active_interp ;
1935-
1936- activate_interpreter (prodesc -> interp );
1937- SvREFCNT_dec (prodesc -> reference );
1938- activate_interpreter (oldinterp );
1939- }
1940- free (prodesc -> proname );
1941- free (prodesc );
1958+ /* ... and release the corresponding refcount, probably deleting it */
1959+ decrement_prodesc_refcount (prodesc );
19421960}
19431961
19441962return false;
19451963}
19461964
19471965
1966+ static void
1967+ free_plperl_function (plperl_proc_desc * prodesc )
1968+ {
1969+ Assert (prodesc -> refcount <=0 );
1970+ /* Release CODE reference, if we have one, from the appropriate interp */
1971+ if (prodesc -> reference )
1972+ {
1973+ plperl_interp_desc * oldinterp = plperl_active_interp ;
1974+
1975+ activate_interpreter (prodesc -> interp );
1976+ SvREFCNT_dec (prodesc -> reference );
1977+ activate_interpreter (oldinterp );
1978+ }
1979+ /* Get rid of what we conveniently can of our own structs */
1980+ /* (FmgrInfo subsidiary info will get leaked ...) */
1981+ if (prodesc -> proname )
1982+ free (prodesc -> proname );
1983+ free (prodesc );
1984+ }
1985+
1986+
19481987static plperl_proc_desc *
19491988compile_plperl_function (Oid fn_oid ,bool is_trigger )
19501989{
@@ -2015,12 +2054,17 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
20152054ereport (ERROR ,
20162055(errcode (ERRCODE_OUT_OF_MEMORY ),
20172056errmsg ("out of memory" )));
2057+ /* Initialize all fields to 0 so free_plperl_function is safe */
20182058MemSet (prodesc ,0 ,sizeof (plperl_proc_desc ));
2059+
20192060prodesc -> proname = strdup (NameStr (procStruct -> proname ));
20202061if (prodesc -> proname == NULL )
2062+ {
2063+ free_plperl_function (prodesc );
20212064ereport (ERROR ,
20222065(errcode (ERRCODE_OUT_OF_MEMORY ),
20232066errmsg ("out of memory" )));
2067+ }
20242068prodesc -> fn_xmin = HeapTupleHeaderGetXmin (procTup -> t_data );
20252069prodesc -> fn_tid = procTup -> t_self ;
20262070
@@ -2035,8 +2079,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
20352079ObjectIdGetDatum (procStruct -> prolang ));
20362080if (!HeapTupleIsValid (langTup ))
20372081{
2038- free (prodesc -> proname );
2039- free (prodesc );
2082+ free_plperl_function (prodesc );
20402083elog (ERROR ,"cache lookup failed for language %u" ,
20412084procStruct -> prolang );
20422085}
@@ -2055,8 +2098,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
20552098ObjectIdGetDatum (procStruct -> prorettype ));
20562099if (!HeapTupleIsValid (typeTup ))
20572100{
2058- free (prodesc -> proname );
2059- free (prodesc );
2101+ free_plperl_function (prodesc );
20602102elog (ERROR ,"cache lookup failed for type %u" ,
20612103procStruct -> prorettype );
20622104}
@@ -2070,17 +2112,15 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
20702112/* okay */ ;
20712113else if (procStruct -> prorettype == TRIGGEROID )
20722114{
2073- free (prodesc -> proname );
2074- free (prodesc );
2115+ free_plperl_function (prodesc );
20752116ereport (ERROR ,
20762117(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
20772118errmsg ("trigger functions can only be called "
20782119"as triggers" )));
20792120}
20802121else
20812122{
2082- free (prodesc -> proname );
2083- free (prodesc );
2123+ free_plperl_function (prodesc );
20842124ereport (ERROR ,
20852125(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
20862126errmsg ("PL/Perl functions cannot return type %s" ,
@@ -2115,8 +2155,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
21152155ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
21162156if (!HeapTupleIsValid (typeTup ))
21172157{
2118- free (prodesc -> proname );
2119- free (prodesc );
2158+ free_plperl_function (prodesc );
21202159elog (ERROR ,"cache lookup failed for type %u" ,
21212160procStruct -> proargtypes .values [i ]);
21222161}
@@ -2125,8 +2164,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
21252164/* Disallow pseudotype argument */
21262165if (typeStruct -> typtype == TYPTYPE_PSEUDO )
21272166{
2128- free (prodesc -> proname );
2129- free (prodesc );
2167+ free_plperl_function (prodesc );
21302168ereport (ERROR ,
21312169(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
21322170errmsg ("PL/Perl functions cannot accept type %s" ,
@@ -2172,8 +2210,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
21722210pfree (proc_source );
21732211if (!prodesc -> reference )/* can this happen? */
21742212{
2175- free (prodesc -> proname );
2176- free (prodesc );
2213+ free_plperl_function (prodesc );
21772214elog (ERROR ,"could not create PL/Perl internal procedure" );
21782215}
21792216
@@ -2185,6 +2222,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
21852222proc_ptr = hash_search (plperl_proc_hash ,& proc_key ,
21862223HASH_ENTER ,NULL );
21872224proc_ptr -> proc_ptr = prodesc ;
2225+ increment_prodesc_refcount (prodesc );
21882226}
21892227
21902228/* restore previous error callback */