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

Commit3d3218a

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 parent0952811 commit3d3218a

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
@@ -58,3 +58,45 @@ select uses_global();
5858
uses_global worked
5959
(1 row)
6060

61+
-- test recovery after "die"
62+
create or replace function just_die() returns void language plperl AS $$
63+
die "just die";
64+
$$;
65+
select just_die();
66+
ERROR: just die at line 2.
67+
CONTEXT: PL/Perl function "just_die"
68+
create or replace function die_caller() returns int language plpgsql as $$
69+
BEGIN
70+
BEGIN
71+
PERFORM just_die();
72+
EXCEPTION WHEN OTHERS THEN
73+
RAISE NOTICE 'caught die';
74+
END;
75+
RETURN 1;
76+
END;
77+
$$;
78+
select die_caller();
79+
NOTICE: caught die
80+
die_caller
81+
------------
82+
1
83+
(1 row)
84+
85+
create or replace function indirect_die_caller() returns int language plperl as $$
86+
my $prepared = spi_prepare('SELECT die_caller() AS fx');
87+
my $a = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
88+
my $b = spi_exec_prepared($prepared)->{rows}->[0]->{fx};
89+
return $a + $b;
90+
$$;
91+
select indirect_die_caller();
92+
NOTICE: caught die
93+
CONTEXT: SQL statement "SELECT die_caller() AS fx"
94+
PL/Perl function "indirect_die_caller"
95+
NOTICE: caught die
96+
CONTEXT: SQL statement "SELECT die_caller() AS fx"
97+
PL/Perl function "indirect_die_caller"
98+
indirect_die_caller
99+
---------------------
100+
2
101+
(1 row)
102+

‎src/pl/plperl/plperl.c

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,27 +1244,32 @@ plperl_call_handler(PG_FUNCTION_ARGS)
12441244
Datumretval;
12451245
plperl_call_data*save_call_data=current_call_data;
12461246
plperl_interp_desc*oldinterp=plperl_active_interp;
1247+
plperl_call_datathis_call_data;
1248+
1249+
/* Initialize current-call status record */
1250+
MemSet(&this_call_data,0,sizeof(this_call_data));
1251+
this_call_data.fcinfo=fcinfo;
12471252

12481253
PG_TRY();
12491254
{
1250-
current_call_data=NULL;
1255+
current_call_data=&this_call_data;
12511256
if (CALLED_AS_TRIGGER(fcinfo))
12521257
retval=PointerGetDatum(plperl_trigger_handler(fcinfo));
12531258
else
12541259
retval=plperl_func_handler(fcinfo);
12551260
}
12561261
PG_CATCH();
12571262
{
1258-
if (current_call_data&&current_call_data->prodesc)
1259-
decrement_prodesc_refcount(current_call_data->prodesc);
1263+
if (this_call_data.prodesc)
1264+
decrement_prodesc_refcount(this_call_data.prodesc);
12601265
current_call_data=save_call_data;
12611266
activate_interpreter(oldinterp);
12621267
PG_RE_THROW();
12631268
}
12641269
PG_END_TRY();
12651270

1266-
if (current_call_data&&current_call_data->prodesc)
1267-
decrement_prodesc_refcount(current_call_data->prodesc);
1271+
if (this_call_data.prodesc)
1272+
decrement_prodesc_refcount(this_call_data.prodesc);
12681273
current_call_data=save_call_data;
12691274
activate_interpreter(oldinterp);
12701275
returnretval;
@@ -1284,8 +1289,12 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
12841289
plperl_proc_descdesc;
12851290
plperl_call_data*save_call_data=current_call_data;
12861291
plperl_interp_desc*oldinterp=plperl_active_interp;
1292+
plperl_call_datathis_call_data;
12871293
ErrorContextCallbackpl_error_context;
12881294

1295+
/* Initialize current-call status record */
1296+
MemSet(&this_call_data,0,sizeof(this_call_data));
1297+
12891298
/* Set up a callback for error reporting */
12901299
pl_error_context.callback=plperl_inline_callback;
12911300
pl_error_context.previous=error_context_stack;
@@ -1316,14 +1325,15 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
13161325
desc.nargs=0;
13171326
desc.reference=NULL;
13181327

1328+
this_call_data.fcinfo=&fake_fcinfo;
1329+
this_call_data.prodesc=&desc;
1330+
/* we do not bother with refcounting the fake prodesc */
1331+
13191332
PG_TRY();
13201333
{
13211334
SV*perlret;
13221335

1323-
current_call_data= (plperl_call_data*)palloc0(sizeof(plperl_call_data));
1324-
current_call_data->fcinfo=&fake_fcinfo;
1325-
current_call_data->prodesc=&desc;
1326-
/* we do not bother with refcounting the fake prodesc */
1336+
current_call_data=&this_call_data;
13271337

13281338
if (SPI_connect()!=SPI_OK_CONNECT)
13291339
elog(ERROR,"could not connect to SPI manager");
@@ -1672,13 +1682,6 @@ plperl_func_handler(PG_FUNCTION_ARGS)
16721682
SV*array_ret=NULL;
16731683
ErrorContextCallbackpl_error_context;
16741684

1675-
/*
1676-
* Create the call_data beforing connecting to SPI, so that it is not
1677-
* allocated in the SPI memory context
1678-
*/
1679-
current_call_data= (plperl_call_data*)palloc0(sizeof(plperl_call_data));
1680-
current_call_data->fcinfo=fcinfo;
1681-
16821685
if (SPI_connect()!=SPI_OK_CONNECT)
16831686
elog(ERROR,"could not connect to SPI manager");
16841687

@@ -1832,13 +1835,6 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
18321835
HV*hvTD;
18331836
ErrorContextCallbackpl_error_context;
18341837

1835-
/*
1836-
* Create the call_data beforing connecting to SPI, so that it is not
1837-
* allocated in the SPI memory context
1838-
*/
1839-
current_call_data= (plperl_call_data*)palloc0(sizeof(plperl_call_data));
1840-
current_call_data->fcinfo=fcinfo;
1841-
18421838
/* Connect to SPI manager */
18431839
if (SPI_connect()!=SPI_OK_CONNECT)
18441840
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
@@ -43,3 +43,33 @@ create or replace function uses_global() returns text language plperl as $$
4343
$$;
4444

4545
select uses_global();
46+
47+
-- test recovery after "die"
48+
49+
create or replacefunctionjust_die() returns void language plperlAS $$
50+
die"just die";
51+
$$;
52+
53+
select just_die();
54+
55+
create or replacefunctiondie_caller() returnsint language plpgsqlas $$
56+
BEGIN
57+
BEGIN
58+
PERFORM just_die();
59+
EXCEPTION WHEN OTHERS THEN
60+
RAISE NOTICE'caught die';
61+
END;
62+
RETURN1;
63+
END;
64+
$$;
65+
66+
select die_caller();
67+
68+
create or replacefunctionindirect_die_caller() returnsint language plperlas $$
69+
my $prepared= spi_prepare('SELECT die_caller() AS fx');
70+
my $a= spi_exec_prepared($prepared)->{rows}->[0]->{fx};
71+
my $b= spi_exec_prepared($prepared)->{rows}->[0]->{fx};
72+
return $a+ $b;
73+
$$;
74+
75+
select indirect_die_caller();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp