Back-patch fix and test case for bug #7516.
authorTom Lane <[email protected]>
Fri, 14 Sep 2012 15:50:19 +0000 (11:50 -0400)
committerTom Lane <[email protected]>
Fri, 14 Sep 2012 15:50:19 +0000 (11:50 -0400)
Back-patch commits 9afc6481117d2dd936e752da0424a2b6b05f6459 and
b8fbbcf37f22c5e8361da939ad0fc4be18a34ca9.  The first of these is really
a minor code cleanup to save a few cycles, but it turns out to provide
a workaround for the misoptimization problem described in bug #7516.
The second commit adds a regression test case.

Back-patch the fix to all active branches.  The test case only works
as far back as 9.0, because it relies on plpgsql which isn't installed
by default before that.  (I didn't have success modifying it into an
all-plperl form that still provoked a crash, though this may just reflect
my lack of Perl-fu.)

src/pl/plperl/plperl.c

index b5cadc31d7e63860cc2e3f0fe97e2d05c09e59be..1536ea0b7dcd8ec31c8bd2807d4bde54e3728788 100644 (file)
@@ -1023,10 +1023,15 @@ plperl_call_handler(PG_FUNCTION_ARGS)
    Datum       retval;
    plperl_call_data *save_call_data = current_call_data;
    plperl_interp_desc *oldinterp = plperl_active_interp;
+   plperl_call_data this_call_data;
+
+   /* Initialize current-call status record */
+   MemSet(&this_call_data, 0, sizeof(this_call_data));
+   this_call_data.fcinfo = fcinfo;
 
    PG_TRY();
    {
-       current_call_data = NULL;
+       current_call_data = &this_call_data;
        if (CALLED_AS_TRIGGER(fcinfo))
            retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
        else
@@ -1034,16 +1039,16 @@ plperl_call_handler(PG_FUNCTION_ARGS)
    }
    PG_CATCH();
    {
-       if (current_call_data && current_call_data->prodesc)
-           decrement_prodesc_refcount(current_call_data->prodesc);
+       if (this_call_data.prodesc)
+           decrement_prodesc_refcount(this_call_data.prodesc);
        current_call_data = save_call_data;
        activate_interpreter(oldinterp);
        PG_RE_THROW();
    }
    PG_END_TRY();
 
-   if (current_call_data && current_call_data->prodesc)
-       decrement_prodesc_refcount(current_call_data->prodesc);
+   if (this_call_data.prodesc)
+       decrement_prodesc_refcount(this_call_data.prodesc);
    current_call_data = save_call_data;
    activate_interpreter(oldinterp);
    return retval;
@@ -1380,13 +1385,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
    ReturnSetInfo *rsi;
    SV         *array_ret = NULL;
 
-   /*
-    * Create the call_data beforing connecting to SPI, so that it is not
-    * allocated in the SPI memory context
-    */
-   current_call_data = (plperl_call_data *) palloc0(sizeof(plperl_call_data));
-   current_call_data->fcinfo = fcinfo;
-
    if (SPI_connect() != SPI_OK_CONNECT)
        elog(ERROR, "could not connect to SPI manager");
 
@@ -1532,13 +1530,6 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
    SV         *svTD;
    HV         *hvTD;
 
-   /*
-    * Create the call_data beforing connecting to SPI, so that it is not
-    * allocated in the SPI memory context
-    */
-   current_call_data = (plperl_call_data *) palloc0(sizeof(plperl_call_data));
-   current_call_data->fcinfo = fcinfo;
-
    /* Connect to SPI manager */
    if (SPI_connect() != SPI_OK_CONNECT)
        elog(ERROR, "could not connect to SPI manager");