Fix multiple causes of breakage in plperl's error handling.

This commit is contained in:
Tom Lane 2003-04-20 21:15:34 +00:00
parent b40bc9eac6
commit b5d0051ecf

View File

@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS. * ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.35 2002/09/21 18:39:26 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.36 2003/04/20 21:15:34 tgl Exp $
* *
**********************************************************************/ **********************************************************************/
@ -92,8 +92,6 @@ typedef struct plperl_proc_desc
* Global data * Global data
**********************************************************************/ **********************************************************************/
static int plperl_firstcall = 1; static int plperl_firstcall = 1;
static int plperl_call_level = 0;
static int plperl_restart_in_progress = 0;
static PerlInterpreter *plperl_interp = NULL; static PerlInterpreter *plperl_interp = NULL;
static HV *plperl_proc_hash = NULL; static HV *plperl_proc_hash = NULL;
@ -143,6 +141,15 @@ plperl_init_all(void)
if (!plperl_firstcall) if (!plperl_firstcall)
return; return;
/************************************************************
* Free the proc hash table
************************************************************/
if (plperl_proc_hash != NULL)
{
hv_undef(plperl_proc_hash);
SvREFCNT_dec((SV *) plperl_proc_hash);
plperl_proc_hash = NULL;
}
/************************************************************ /************************************************************
* Destroy the existing Perl interpreter * Destroy the existing Perl interpreter
@ -154,16 +161,6 @@ plperl_init_all(void)
plperl_interp = NULL; plperl_interp = NULL;
} }
/************************************************************
* Free the proc hash table
************************************************************/
if (plperl_proc_hash != NULL)
{
hv_undef(plperl_proc_hash);
SvREFCNT_dec((SV *) plperl_proc_hash);
plperl_proc_hash = NULL;
}
/************************************************************ /************************************************************
* Now recreate a new Perl interpreter * Now recreate a new Perl interpreter
************************************************************/ ************************************************************/
@ -202,8 +199,6 @@ plperl_init_interp(void)
perl_parse(plperl_interp, plperl_init_shared_libs, 3, embedding, NULL); perl_parse(plperl_interp, plperl_init_shared_libs, 3, embedding, NULL);
perl_run(plperl_interp); perl_run(plperl_interp);
/************************************************************ /************************************************************
* Initialize the proc and query hash tables * Initialize the proc and query hash tables
************************************************************/ ************************************************************/
@ -212,7 +207,6 @@ plperl_init_interp(void)
} }
/********************************************************************** /**********************************************************************
* plperl_call_handler - This is the only visible function * plperl_call_handler - This is the only visible function
* of the PL interpreter. The PostgreSQL * of the PL interpreter. The PostgreSQL
@ -229,7 +223,7 @@ plperl_call_handler(PG_FUNCTION_ARGS)
Datum retval; Datum retval;
/************************************************************ /************************************************************
* Initialize interpreters on first call * Initialize interpreter on first call
************************************************************/ ************************************************************/
if (plperl_firstcall) if (plperl_firstcall)
plperl_init_all(); plperl_init_all();
@ -239,10 +233,6 @@ plperl_call_handler(PG_FUNCTION_ARGS)
************************************************************/ ************************************************************/
if (SPI_connect() != SPI_OK_CONNECT) if (SPI_connect() != SPI_OK_CONNECT)
elog(ERROR, "plperl: cannot connect to SPI manager"); elog(ERROR, "plperl: cannot connect to SPI manager");
/************************************************************
* Keep track about the nesting of Perl-SPI-Perl-... calls
************************************************************/
plperl_call_level++;
/************************************************************ /************************************************************
* Determine if called as function or trigger and * Determine if called as function or trigger and
@ -261,8 +251,6 @@ plperl_call_handler(PG_FUNCTION_ARGS)
else else
retval = plperl_func_handler(fcinfo); retval = plperl_func_handler(fcinfo);
plperl_call_level--;
return retval; return retval;
} }
@ -272,13 +260,11 @@ plperl_call_handler(PG_FUNCTION_ARGS)
* create the anonymous subroutine whose text is in the SV. * create the anonymous subroutine whose text is in the SV.
* Returns the SV containing the RV to the closure. * Returns the SV containing the RV to the closure.
**********************************************************************/ **********************************************************************/
static static SV *
SV *
plperl_create_sub(char *s, bool trusted) plperl_create_sub(char *s, bool trusted)
{ {
dSP; dSP;
SV *subref;
SV *subref = NULL;
int count; int count;
ENTER; ENTER;
@ -286,10 +272,23 @@ plperl_create_sub(char *s, bool trusted)
PUSHMARK(SP); PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(s, 0))); XPUSHs(sv_2mortal(newSVpv(s, 0)));
PUTBACK; PUTBACK;
/*
* G_KEEPERR seems to be needed here, else we don't recognize compile
* errors properly. Perhaps it's because there's another level of eval
* inside mksafefunc?
*/
count = perl_call_pv((trusted ? "mksafefunc" : "mkunsafefunc"), count = perl_call_pv((trusted ? "mksafefunc" : "mkunsafefunc"),
G_SCALAR | G_EVAL | G_KEEPERR); G_SCALAR | G_EVAL | G_KEEPERR);
SPAGAIN; SPAGAIN;
if (count != 1)
{
PUTBACK;
FREETMPS;
LEAVE;
elog(ERROR, "plperl: didn't get a return item from mksafefunc");
}
if (SvTRUE(ERRSV)) if (SvTRUE(ERRSV))
{ {
POPs; POPs;
@ -299,9 +298,6 @@ plperl_create_sub(char *s, bool trusted)
elog(ERROR, "creation of function failed: %s", SvPV(ERRSV, PL_na)); elog(ERROR, "creation of function failed: %s", SvPV(ERRSV, PL_na));
} }
if (count != 1)
elog(ERROR, "creation of function failed - no return from mksafefunc");
/* /*
* need to make a deep copy of the return. it comes off the stack as a * need to make a deep copy of the return. it comes off the stack as a
* temporary. * temporary.
@ -324,6 +320,7 @@ plperl_create_sub(char *s, bool trusted)
PUTBACK; PUTBACK;
FREETMPS; FREETMPS;
LEAVE; LEAVE;
return subref; return subref;
} }
@ -352,21 +349,18 @@ plperl_init_shared_libs(pTHX)
* plperl_call_perl_func() - calls a perl function through the RV * plperl_call_perl_func() - calls a perl function through the RV
* stored in the prodesc structure. massages the input parms properly * stored in the prodesc structure. massages the input parms properly
**********************************************************************/ **********************************************************************/
static static SV *
SV *
plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo) plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo)
{ {
dSP; dSP;
SV *retval; SV *retval;
int i; int i;
int count; int count;
ENTER; ENTER;
SAVETMPS; SAVETMPS;
PUSHMARK(sp); PUSHMARK(SP);
for (i = 0; i < desc->nargs; i++) for (i = 0; i < desc->nargs; i++)
{ {
if (desc->arg_is_rel[i]) if (desc->arg_is_rel[i])
@ -401,7 +395,9 @@ plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo)
} }
} }
PUTBACK; PUTBACK;
count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL | G_KEEPERR);
/* Do NOT use G_KEEPERR here */
count = perl_call_sv(desc->reference, G_SCALAR | G_EVAL);
SPAGAIN; SPAGAIN;
@ -424,16 +420,14 @@ plperl_call_perl_func(plperl_proc_desc * desc, FunctionCallInfo fcinfo)
retval = newSVsv(POPs); retval = newSVsv(POPs);
PUTBACK; PUTBACK;
FREETMPS; FREETMPS;
LEAVE; LEAVE;
return retval; return retval;
} }
/********************************************************************** /**********************************************************************
* plperl_func_handler() - Handler for regular function calls * plperl_func_handler() - Handler for regular function calls
**********************************************************************/ **********************************************************************/
@ -443,23 +437,10 @@ plperl_func_handler(PG_FUNCTION_ARGS)
plperl_proc_desc *prodesc; plperl_proc_desc *prodesc;
SV *perlret; SV *perlret;
Datum retval; Datum retval;
sigjmp_buf save_restart;
/* Find or compile the function */ /* Find or compile the function */
prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false); prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false);
/* Set up error handling */
memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
if (sigsetjmp(Warn_restart, 1) != 0)
{
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
plperl_restart_in_progress = 1;
if (--plperl_call_level == 0)
plperl_restart_in_progress = 0;
siglongjmp(Warn_restart, 1);
}
/************************************************************ /************************************************************
* Call the Perl function * Call the Perl function
************************************************************/ ************************************************************/
@ -490,14 +471,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
SvREFCNT_dec(perlret); SvREFCNT_dec(perlret);
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
if (plperl_restart_in_progress)
{
if (--plperl_call_level == 0)
plperl_restart_in_progress = 0;
siglongjmp(Warn_restart, 1);
}
return retval; return retval;
} }
@ -734,7 +707,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger)
* plperl_build_tuple_argument() - Build a string for a ref to a hash * plperl_build_tuple_argument() - Build a string for a ref to a hash
* from all attributes of a given tuple * from all attributes of a given tuple
**********************************************************************/ **********************************************************************/
static SV * static SV *
plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc) plperl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc)
{ {
int i; int i;