[GENERAL] Small patch for PL/Perl Misbehavior with Runtime Error Reporting

Started by John Worsleyover 23 years ago6 messageshackers
Jump to latest
#1John Worsley
lx@openvein.com

Good day,

I just stumbled across this peculiarity in PL/Perl today writing a method
to invoke Perl Regexes from a function: if a run-time error is raised in
an otherwise good function, the function will never run correctly again
until the connection to the database is reset. I poked around in the code
and it appears that it's because when elog() raises the ERROR, it doesn't
first take action to erase the system error message ($@) and consequently
every subsequent run has an error raised, even if it runs successfully.

For example:

-- This comparison works fine.

template1=# SELECT perl_re_match('test', 'test');
perl_re_match
---------------
t
(1 row)

-- This one dies, for obvious reasons.

template1=# SELECT perl_re_match('test', 't{1}+?');
ERROR: plperl: error from function: (in cleanup) Nested quantifiers
before HERE mark in regex m/t{1}+ << HERE ?/ at (eval 2) line 4.

-- This should work fine again, but we still have this error raised...!

template1=# SELECT perl_re_match('test', 'test');
ERROR: plperl: error from function: (in cleanup) Nested quantifiers
before HERE mark in regex m/t{1}+ << HERE ?/ at (eval 2) line 4.

I don't know if the following is the best way to solve it, but I got
around it by modifying the error report in this part of PL/Perl to be a
NOTICE, cleared the $@ variable, and then raised the fatal ERROR. A simple
three line patch to plperl.c follows, and is attached.

src/pl/plperl/plperl.c:
443c443,445
< elog(ERROR, "plperl: error from function: %s", SvPV(ERRSV, PL_na));
---

elog(NOTICE, "plperl: error from function: %s", SvPV(ERRSV, PL_na));
sv_setpv(perl_get_sv("@",FALSE),"");
elog(ERROR, "plperl: error was fatal.");

Best Regards,
Jw.
--
John Worsley - lx@openvein.com
http://www.openvein.com/

Attachments:

plperl.c.difftext/plain; charset=US-ASCII; name=plperl.c.diffDownload+3-1
#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: John Worsley (#1)
Re: [GENERAL] Small patch for PL/Perl Misbehavior with Runtime Error Reporting

John Worsley <lx@openvein.com> writes:

I just stumbled across this peculiarity in PL/Perl today writing a method
to invoke Perl Regexes from a function: if a run-time error is raised in
an otherwise good function, the function will never run correctly again
until the connection to the database is reset. I poked around in the code
and it appears that it's because when elog() raises the ERROR, it doesn't
first take action to erase the system error message ($@) and consequently
every subsequent run has an error raised, even if it runs successfully.

That seems a little weird. Does Perl really expect people to do that
(ie, is it a documented part of some API)? I wonder whether there is
some other action that we're supposed to take instead, but are
missing...

src/pl/plperl/plperl.c:
443c443,445
< elog(ERROR, "plperl: error from function: %s", SvPV(ERRSV, PL_na));
---

elog(NOTICE, "plperl: error from function: %s", SvPV(ERRSV, PL_na));
sv_setpv(perl_get_sv("@",FALSE),"");
elog(ERROR, "plperl: error was fatal.");

If this is what we'd have to do, I think a better way would be

perlerrmsg = pstrdup(SvPV(ERRSV, PL_na));
sv_setpv(perl_get_sv("@",FALSE),"");
elog(ERROR, "plperl: error from function: %s", perlerrmsg);

Splitting the ERROR into a NOTICE with the useful info and an ERROR
without any isn't real good, because the NOTICE could get dropped on the
floor (either because of min_message_level or a client that just plain
loses notices).

regards, tom lane

#3John Worsley
lx@openvein.com
In reply to: Tom Lane (#2)
Re: [GENERAL] Small patch for PL/Perl Misbehavior with

On Thu, 3 Oct 2002, Tom Lane wrote:

That seems a little weird. Does Perl really expect people to do that
(ie, is it a documented part of some API)? I wonder whether there is
some other action that we're supposed to take instead, but are
missing...

Not that I know of: clearing out the $@ variable manually was just my way
of getting around the problem in practice. I think the underlying issue
may be tied to the fact that it's running a function generated within a
Safe Module, but I'm not enough of a Perl Guru to say anything more
decisive than that.

If this is what we'd have to do, I think a better way would be

perlerrmsg = pstrdup(SvPV(ERRSV, PL_na));
sv_setpv(perl_get_sv("@",FALSE),"");
elog(ERROR, "plperl: error from function: %s", perlerrmsg);
Splitting the ERROR into a NOTICE with the useful info and an ERROR
without any isn't real good, because the NOTICE could get dropped on the
floor (either because of min_message_level or a client that just plain
loses notices).

Yeah, that's a cleaner solution. I take it anything pstrdup'd by
PostgreSQL gets freed automatically by the backend? (I wasn't familiar
enough with the backend to know how to ask for memory confident in the
understanding that it would at some point be freed. ;)

Jw.
--
John Worsley - lx@openvein.com
http://www.openvein.com/

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: John Worsley (#3)
Re: [GENERAL] Small patch for PL/Perl Misbehavior with Runtime Error Reporting

John Worsley <lx@openvein.com> writes:

Yeah, that's a cleaner solution. I take it anything pstrdup'd by
PostgreSQL gets freed automatically by the backend?

Pretty much. The only situation where it wouldn't be is if
CurrentMemoryContext is pointing at TopMemoryContext or another
long-lived context --- but we are *very* chary about how much code we
allow to run with such a setting. User-definable functions can safely
assume that palloc'd space will live only long enough for them to return
something to their caller in it.

regards, tom lane

#5Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#2)
Re: [GENERAL] Small patch for PL/Perl Misbehavior with Runtime

Did we ever address this plperl issue? I see the code unchanged in CVS.

---------------------------------------------------------------------------

Tom Lane wrote:

John Worsley <lx@openvein.com> writes:

I just stumbled across this peculiarity in PL/Perl today writing a method
to invoke Perl Regexes from a function: if a run-time error is raised in
an otherwise good function, the function will never run correctly again
until the connection to the database is reset. I poked around in the code
and it appears that it's because when elog() raises the ERROR, it doesn't
first take action to erase the system error message ($@) and consequently
every subsequent run has an error raised, even if it runs successfully.

That seems a little weird. Does Perl really expect people to do that
(ie, is it a documented part of some API)? I wonder whether there is
some other action that we're supposed to take instead, but are
missing...

src/pl/plperl/plperl.c:
443c443,445
< elog(ERROR, "plperl: error from function: %s", SvPV(ERRSV, PL_na));
---

elog(NOTICE, "plperl: error from function: %s", SvPV(ERRSV, PL_na));
sv_setpv(perl_get_sv("@",FALSE),"");
elog(ERROR, "plperl: error was fatal.");

If this is what we'd have to do, I think a better way would be

perlerrmsg = pstrdup(SvPV(ERRSV, PL_na));
sv_setpv(perl_get_sv("@",FALSE),"");
elog(ERROR, "plperl: error from function: %s", perlerrmsg);

Splitting the ERROR into a NOTICE with the useful info and an ERROR
without any isn't real good, because the NOTICE could get dropped on the
floor (either because of min_message_level or a client that just plain
loses notices).

regards, tom lane

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#5)
Re: [GENERAL] Small patch for PL/Perl Misbehavior with Runtime Error Reporting

Bruce Momjian <pgman@candle.pha.pa.us> writes:

Did we ever address this plperl issue? I see the code unchanged in CVS.

It's fixed, although not in the way proposed in that patch.

regards, tom lane