@@ -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{
101107 char * proname ; /* user name of procedure */
102- TransactionId fn_xmin ;
108+ TransactionId fn_xmin ; /* xmin/TID of procedure's pg_proc tuple */
103109 ItemPointerData fn_tid ;
110+ int refcount ; /* reference count of this struct */
111+ SV * reference ; /* CODE reference for Perl sub */
104112 plperl_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? */
107115 bool fn_retistuple ; /* true, if function returns tuple */
108116 bool fn_retisset ; /* true, if function returns set */
109117 bool fn_retisarray ; /* true if function returns array */
118+ /* Conversion info for function's result type: */
110119 Oid result_oid ; /* Oid of result type */
111120 FmgrInfo result_in_func ; /* I/O function and arg for result type */
112121 Oid result_typioparam ;
122+ /* Conversion info for function's argument types: */
113123 int nargs ;
114124 FmgrInfo arg_out_func [FUNC_MAX_ARGS ];
115125 bool arg_is_rowtype [FUNC_MAX_ARGS ];
116126 Oid 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
16901709 PG_TRY ();
16911710 {
1711+ current_call_data = NULL ;
16921712 if (CALLED_AS_TRIGGER (fcinfo ))
16931713 retval = PointerGetDatum (plperl_trigger_handler (fcinfo ));
16941714 else
16951715 retval = plperl_func_handler (fcinfo );
16961716 }
16971717 PG_CATCH ();
16981718 {
1719+ if (current_call_data && current_call_data -> prodesc )
1720+ decrement_prodesc_refcount (current_call_data -> prodesc );
16991721 current_call_data = save_call_data ;
17001722 activate_interpreter (oldinterp );
17011723 PG_RE_THROW ();
17021724 }
17031725 PG_END_TRY ();
17041726
1727+ if (current_call_data && current_call_data -> prodesc )
1728+ decrement_prodesc_refcount (current_call_data -> prodesc );
17051729 current_call_data = save_call_data ;
17061730 activate_interpreter (oldinterp );
17071731 return retval ;
@@ -1753,14 +1777,15 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
17531777 desc .nargs = 0 ;
17541778 desc .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-
17601780 PG_TRY ();
17611781 {
17621782 SV * 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+
17641789 if (SPI_connect () != SPI_OK_CONNECT )
17651790 elog (ERROR , "could not connect to SPI manager" );
17661791
@@ -2154,6 +2179,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
21542179
21552180 prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , false);
21562181 current_call_data -> prodesc = prodesc ;
2182+ increment_prodesc_refcount (prodesc );
21572183
21582184 /* Set a callback for error reporting */
21592185 pl_error_context .callback = plperl_exec_callback ;
@@ -2274,6 +2300,7 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
22742300 /* Find or compile the function */
22752301 prodesc = compile_plperl_function (fcinfo -> flinfo -> fn_oid , true);
22762302 current_call_data -> prodesc = prodesc ;
2303+ increment_prodesc_refcount (prodesc );
22772304
22782305 /* Set a callback for error reporting */
22792306 pl_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 ... */
23852412 proc_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
23992417 return 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)
24702509 ereport (ERROR ,
24712510 (errcode (ERRCODE_OUT_OF_MEMORY ),
24722511 errmsg ("out of memory" )));
2512+ /* Initialize all fields to 0 so free_plperl_function is safe */
24732513 MemSet (prodesc , 0 , sizeof (plperl_proc_desc ));
2514+
24742515 prodesc -> proname = strdup (NameStr (procStruct -> proname ));
24752516 if (prodesc -> proname == NULL )
2517+ {
2518+ free_plperl_function (prodesc );
24762519 ereport (ERROR ,
24772520 (errcode (ERRCODE_OUT_OF_MEMORY ),
24782521 errmsg ("out of memory" )));
2522+ }
24792523 prodesc -> fn_xmin = HeapTupleHeaderGetXmin (procTup -> t_data );
24802524 prodesc -> fn_tid = procTup -> t_self ;
24812525
@@ -2490,8 +2534,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
24902534 ObjectIdGetDatum (procStruct -> prolang ));
24912535 if (!HeapTupleIsValid (langTup ))
24922536 {
2493- free (prodesc -> proname );
2494- free (prodesc );
2537+ free_plperl_function (prodesc );
24952538 elog (ERROR , "cache lookup failed for language %u" ,
24962539 procStruct -> prolang );
24972540 }
@@ -2510,8 +2553,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25102553 ObjectIdGetDatum (procStruct -> prorettype ));
25112554 if (!HeapTupleIsValid (typeTup ))
25122555 {
2513- free (prodesc -> proname );
2514- free (prodesc );
2556+ free_plperl_function (prodesc );
25152557 elog (ERROR , "cache lookup failed for type %u" ,
25162558 procStruct -> prorettype );
25172559 }
@@ -2525,17 +2567,15 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25252567 /* okay */ ;
25262568 else if (procStruct -> prorettype == TRIGGEROID )
25272569 {
2528- free (prodesc -> proname );
2529- free (prodesc );
2570+ free_plperl_function (prodesc );
25302571 ereport (ERROR ,
25312572 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25322573 errmsg ("trigger functions can only be called "
25332574 "as triggers" )));
25342575 }
25352576 else
25362577 {
2537- free (prodesc -> proname );
2538- free (prodesc );
2578+ free_plperl_function (prodesc );
25392579 ereport (ERROR ,
25402580 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25412581 errmsg ("PL/Perl functions cannot return type %s" ,
@@ -2570,8 +2610,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25702610 ObjectIdGetDatum (procStruct -> proargtypes .values [i ]));
25712611 if (!HeapTupleIsValid (typeTup ))
25722612 {
2573- free (prodesc -> proname );
2574- free (prodesc );
2613+ free_plperl_function (prodesc );
25752614 elog (ERROR , "cache lookup failed for type %u" ,
25762615 procStruct -> proargtypes .values [i ]);
25772616 }
@@ -2581,8 +2620,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
25812620 if (typeStruct -> typtype == TYPTYPE_PSEUDO &&
25822621 procStruct -> proargtypes .values [i ] != RECORDOID )
25832622 {
2584- free (prodesc -> proname );
2585- free (prodesc );
2623+ free_plperl_function (prodesc );
25862624 ereport (ERROR ,
25872625 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
25882626 errmsg ("PL/Perl functions cannot accept type %s" ,
@@ -2635,8 +2673,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
26352673 pfree (proc_source );
26362674 if (!prodesc -> reference ) /* can this happen? */
26372675 {
2638- free (prodesc -> proname );
2639- free (prodesc );
2676+ free_plperl_function (prodesc );
26402677 elog (ERROR , "could not create PL/Perl internal procedure" );
26412678 }
26422679
@@ -2648,6 +2685,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
26482685 proc_ptr = hash_search (plperl_proc_hash , & proc_key ,
26492686 HASH_ENTER , NULL );
26502687 proc_ptr -> proc_ptr = prodesc ;
2688+ increment_prodesc_refcount (prodesc );
26512689 }
26522690
26532691 /* restore previous error callback */
0 commit comments