1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-11 10:01:57 +03:00

Back-patch fix and test case for bug #7516.

Back-patch commits 9afc648111 and
b8fbbcf37f.  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.)
This commit is contained in:
Tom Lane
2012-09-14 11:50:02 -04:00
parent eb6e9b5ea4
commit 97d8ad170f
3 changed files with 91 additions and 23 deletions

View File

@ -1696,10 +1696,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
@ -1707,16 +1712,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;
@ -1736,8 +1741,12 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
plperl_proc_desc desc;
plperl_call_data *save_call_data = current_call_data;
plperl_interp_desc *oldinterp = plperl_active_interp;
plperl_call_data this_call_data;
ErrorContextCallback pl_error_context;
/* Initialize current-call status record */
MemSet(&this_call_data, 0, sizeof(this_call_data));
/* Set up a callback for error reporting */
pl_error_context.callback = plperl_inline_callback;
pl_error_context.previous = error_context_stack;
@ -1768,14 +1777,15 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
desc.nargs = 0;
desc.reference = NULL;
this_call_data.fcinfo = &fake_fcinfo;
this_call_data.prodesc = &desc;
/* we do not bother with refcounting the fake prodesc */
PG_TRY();
{
SV *perlret;
current_call_data = (plperl_call_data *) palloc0(sizeof(plperl_call_data));
current_call_data->fcinfo = &fake_fcinfo;
current_call_data->prodesc = &desc;
/* we do not bother with refcounting the fake prodesc */
current_call_data = &this_call_data;
if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "could not connect to SPI manager");
@ -2158,13 +2168,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
ReturnSetInfo *rsi;
ErrorContextCallback pl_error_context;
/*
* Create the call_data before 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");
@ -2277,13 +2280,6 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
HV *hvTD;
ErrorContextCallback pl_error_context;
/*
* Create the call_data before 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");