Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit87802a1

Browse files
committed
Back-patch fix and test case for bug #7516.
Back-patch commits9afc648 andb8fbbcf. The first of these is reallya minor code cleanup to save a few cycles, but it turns out to providea 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 worksas far back as 9.0, because it relies on plpgsql which isn't installedby default before that. (I didn't have success modifying it into anall-plperl form that still provoked a crash, though this may just reflectmy lack of Perl-fu.)
1 parentfef2c17 commit87802a1

File tree

3 files changed

+91
-23
lines changed

3 files changed

+91
-23
lines changed

‎src/pl/plperl/expected/plperl_elog.out

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,45 @@ select uses_global();
6262
do language plperl $$ elog(NOTICE, ${^TAINT}); $$;
6363
NOTICE: 0
6464
CONTEXT: PL/Perl anonymous code block
65+
-- test recovery after "die"
66+
create or replace function just_die() returns void language plperl AS $$
67+
die "just die";
68+
$$;
69+
select just_die();
70+
ERROR: just die at line 2.
71+
CONTEXT: PL/Perl function "just_die"
72+
create or replace function die_caller() returns int language plpgsql as $$
73+
BEGIN
74+
BEGIN
75+
PERFORM just_die();
76+
EXCEPTION WHEN OTHERS THEN
77+
RAISE NOTICE 'caught die';
78+
END;
79+
RETURN 1;
80+
END;
81+
$$;
82+
select die_caller();
83+
NOTICE: caught die
84+
die_caller
85+
------------
86+
1
87+
(1 row)
88+
89+
create or replace function indirect_die_caller() returns int language plperl as $$
90+
my $prepared = spi_prepare('SELECT die_caller() AS fx');
91+
my $a = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
92+
my $b = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
93+
return $a + $b;
94+
$$;
95+
select indirect_die_caller();
96+
NOTICE: caught die
97+
CONTEXT: SQL statement "SELECT die_caller() AS fx"
98+
PL/Perl function "indirect_die_caller"
99+
NOTICE: caught die
100+
CONTEXT: SQL statement "SELECT die_caller() AS fx"
101+
PL/Perl function "indirect_die_caller"
102+
indirect_die_caller
103+
---------------------
104+
2
105+
(1 row)
106+

‎src/pl/plperl/plperl.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,27 +1695,32 @@ plperl_call_handler(PG_FUNCTION_ARGS)
16951695
Datumretval;
16961696
plperl_call_data*save_call_data=current_call_data;
16971697
plperl_interp_desc*oldinterp=plperl_active_interp;
1698+
plperl_call_datathis_call_data;
1699+
1700+
/* Initialize current-call status record */
1701+
MemSet(&this_call_data,0,sizeof(this_call_data));
1702+
this_call_data.fcinfo=fcinfo;
16981703

16991704
PG_TRY();
17001705
{
1701-
current_call_data=NULL;
1706+
current_call_data=&this_call_data;
17021707
if (CALLED_AS_TRIGGER(fcinfo))
17031708
retval=PointerGetDatum(plperl_trigger_handler(fcinfo));
17041709
else
17051710
retval=plperl_func_handler(fcinfo);
17061711
}
17071712
PG_CATCH();
17081713
{
1709-
if (current_call_data&&current_call_data->prodesc)
1710-
decrement_prodesc_refcount(current_call_data->prodesc);
1714+
if (this_call_data.prodesc)
1715+
decrement_prodesc_refcount(this_call_data.prodesc);
17111716
current_call_data=save_call_data;
17121717
activate_interpreter(oldinterp);
17131718
PG_RE_THROW();
17141719
}
17151720
PG_END_TRY();
17161721

1717-
if (current_call_data&&current_call_data->prodesc)
1718-
decrement_prodesc_refcount(current_call_data->prodesc);
1722+
if (this_call_data.prodesc)
1723+
decrement_prodesc_refcount(this_call_data.prodesc);
17191724
current_call_data=save_call_data;
17201725
activate_interpreter(oldinterp);
17211726
returnretval;
@@ -1735,8 +1740,12 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
17351740
plperl_proc_descdesc;
17361741
plperl_call_data*save_call_data=current_call_data;
17371742
plperl_interp_desc*oldinterp=plperl_active_interp;
1743+
plperl_call_datathis_call_data;
17381744
ErrorContextCallbackpl_error_context;
17391745

1746+
/* Initialize current-call status record */
1747+
MemSet(&this_call_data,0,sizeof(this_call_data));
1748+
17401749
/* Set up a callback for error reporting */
17411750
pl_error_context.callback=plperl_inline_callback;
17421751
pl_error_context.previous=error_context_stack;
@@ -1767,14 +1776,15 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
17671776
desc.nargs=0;
17681777
desc.reference=NULL;
17691778

1779+
this_call_data.fcinfo=&fake_fcinfo;
1780+
this_call_data.prodesc=&desc;
1781+
/* we do not bother with refcounting the fake prodesc */
1782+
17701783
PG_TRY();
17711784
{
17721785
SV*perlret;
17731786

1774-
current_call_data= (plperl_call_data*)palloc0(sizeof(plperl_call_data));
1775-
current_call_data->fcinfo=&fake_fcinfo;
1776-
current_call_data->prodesc=&desc;
1777-
/* we do not bother with refcounting the fake prodesc */
1787+
current_call_data=&this_call_data;
17781788

17791789
if (SPI_connect()!=SPI_OK_CONNECT)
17801790
elog(ERROR,"could not connect to SPI manager");
@@ -2157,13 +2167,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
21572167
ReturnSetInfo*rsi;
21582168
ErrorContextCallbackpl_error_context;
21592169

2160-
/*
2161-
* Create the call_data before connecting to SPI, so that it is not
2162-
* allocated in the SPI memory context
2163-
*/
2164-
current_call_data= (plperl_call_data*)palloc0(sizeof(plperl_call_data));
2165-
current_call_data->fcinfo=fcinfo;
2166-
21672170
if (SPI_connect()!=SPI_OK_CONNECT)
21682171
elog(ERROR,"could not connect to SPI manager");
21692172

@@ -2276,13 +2279,6 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
22762279
HV*hvTD;
22772280
ErrorContextCallbackpl_error_context;
22782281

2279-
/*
2280-
* Create the call_data before connecting to SPI, so that it is not
2281-
* allocated in the SPI memory context
2282-
*/
2283-
current_call_data= (plperl_call_data*)palloc0(sizeof(plperl_call_data));
2284-
current_call_data->fcinfo=fcinfo;
2285-
22862282
/* Connect to SPI manager */
22872283
if (SPI_connect()!=SPI_OK_CONNECT)
22882284
elog(ERROR,"could not connect to SPI manager");

‎src/pl/plperl/sql/plperl_elog.sql

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,33 @@ select uses_global();
4646

4747
-- make sure we don't choke on readonly values
4848
do language plperl $$ elog(NOTICE, ${^TAINT}); $$;
49+
50+
-- test recovery after "die"
51+
52+
create or replacefunctionjust_die() returns void language plperlAS $$
53+
die"just die";
54+
$$;
55+
56+
select just_die();
57+
58+
create or replacefunctiondie_caller() returnsint language plpgsqlas $$
59+
BEGIN
60+
BEGIN
61+
PERFORM just_die();
62+
EXCEPTION WHEN OTHERS THEN
63+
RAISE NOTICE'caught die';
64+
END;
65+
RETURN1;
66+
END;
67+
$$;
68+
69+
select die_caller();
70+
71+
create or replacefunctionindirect_die_caller() returnsint language plperlas $$
72+
my $prepared= spi_prepare('SELECT die_caller() AS fx');
73+
my $a= spi_exec_prepared($prepared)->{rows}->[0]->{fx};
74+
my $b= spi_exec_prepared($prepared)->{rows}->[0]->{fx};
75+
return $a+ $b;
76+
$$;
77+
78+
select indirect_die_caller();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp