Skip to content

Commit 88f1fd2

Browse files
committed
Fix oversight in PG_RE_THROW processing: it's entirely possible that there
isn't any place to throw the error to. If so, we should treat the error as FATAL, just as we would have if it'd been thrown outside the PG_TRY block to begin with. Although this is clearly a *potential* source of bugs, it is not clear at the moment whether it is an *actual* source of bugs; there may not presently be any PG_TRY blocks in code that can be reached with no outer longjmp catcher. So for the moment I'm going to be conservative and not back-patch this. The change breaks ABI for users of PG_RE_THROW and hence might create compatibility problems for loadable modules, so we should not put it into released branches without proof that it's needed.
1 parent d6013a3 commit 88f1fd2

File tree

2 files changed

+59
-3
lines changed

2 files changed

+59
-3
lines changed

src/backend/utils/error/elog.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
*
4343
*
4444
* IDENTIFICATION
45-
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.183 2007/03/02 23:37:23 tgl Exp $
45+
* $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.184 2007/05/02 15:32:41 tgl Exp $
4646
*
4747
*-------------------------------------------------------------------------
4848
*/
@@ -1099,6 +1099,61 @@ ReThrowError(ErrorData *edata)
10991099
PG_RE_THROW();
11001100
}
11011101

1102+
/*
1103+
* pg_re_throw --- out-of-line implementation of PG_RE_THROW() macro
1104+
*/
1105+
void
1106+
pg_re_throw(void)
1107+
{
1108+
/* If possible, throw the error to the next outer setjmp handler */
1109+
if (PG_exception_stack != NULL)
1110+
siglongjmp(*PG_exception_stack, 1);
1111+
else
1112+
{
1113+
/*
1114+
* If we get here, elog(ERROR) was thrown inside a PG_TRY block, which
1115+
* we have now exited only to discover that there is no outer setjmp
1116+
* handler to pass the error to. Had the error been thrown outside the
1117+
* block to begin with, we'd have promoted the error to FATAL, so the
1118+
* correct behavior is to make it FATAL now; that is, emit it and then
1119+
* call proc_exit.
1120+
*/
1121+
ErrorData *edata = &errordata[errordata_stack_depth];
1122+
1123+
Assert(errordata_stack_depth >= 0);
1124+
Assert(edata->elevel == ERROR);
1125+
edata->elevel = FATAL;
1126+
1127+
/*
1128+
* At least in principle, the increase in severity could have changed
1129+
* where-to-output decisions, so recalculate. This should stay in
1130+
* sync with errstart(), which see for comments.
1131+
*/
1132+
if (IsPostmasterEnvironment)
1133+
edata->output_to_server = is_log_level_output(FATAL,
1134+
log_min_messages);
1135+
else
1136+
edata->output_to_server = (FATAL >= log_min_messages);
1137+
if (whereToSendOutput == DestRemote)
1138+
{
1139+
if (ClientAuthInProgress)
1140+
edata->output_to_client = true;
1141+
else
1142+
edata->output_to_client = (FATAL >= client_min_messages);
1143+
}
1144+
1145+
/*
1146+
* We can use errfinish() for the rest, but we don't want it to call
1147+
* any error context routines a second time. Since we know we are
1148+
* about to exit, it should be OK to just clear the context stack.
1149+
*/
1150+
error_context_stack = NULL;
1151+
1152+
errfinish(0);
1153+
}
1154+
}
1155+
1156+
11021157
/*
11031158
* Initialization of error output file
11041159
*/

src/include/utils/elog.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.84 2007/03/02 23:37:23 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.85 2007/05/02 15:32:42 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -223,7 +223,7 @@ extern DLLIMPORT ErrorContextCallback *error_context_stack;
223223
} while (0)
224224

225225
#define PG_RE_THROW() \
226-
siglongjmp(*PG_exception_stack, 1)
226+
pg_re_throw()
227227

228228
extern DLLIMPORT sigjmp_buf *PG_exception_stack;
229229

@@ -262,6 +262,7 @@ extern ErrorData *CopyErrorData(void);
262262
extern void FreeErrorData(ErrorData *edata);
263263
extern void FlushErrorState(void);
264264
extern void ReThrowError(ErrorData *edata);
265+
extern void pg_re_throw(void);
265266

266267

267268
/* GUC-configurable parameters */

0 commit comments

Comments
 (0)