diff options
Diffstat (limited to 'src/backend/utils/error/elog.c')
-rw-r--r-- | src/backend/utils/error/elog.c | 75 |
1 files changed, 55 insertions, 20 deletions
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 42df11cc1cf..342ee0e314b 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -42,7 +42,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.167.2.6 2008/07/08 22:18:02 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.167.2.7 2008/10/27 19:37:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -124,6 +124,21 @@ static const char *error_severity(int elevel); static void append_with_tabs(StringInfo buf, const char *str); static void write_pipe_chunks(int fd, char *data, int len); + +/* + * in_error_recursion_trouble --- are we at risk of infinite error recursion? + * + * This function exists to provide common control of various fallback steps + * that we take if we think we are facing infinite error recursion. See the + * callers for details. + */ +bool +in_error_recursion_trouble(void) +{ + /* Pull the plug if recurse more than once */ + return (recursion_depth > 2); +} + /* * errstart --- begin an error-reporting cycle * @@ -259,12 +274,12 @@ errstart(int elevel, const char *filename, int lineno, MemoryContextReset(ErrorContext); /* - * If we recurse more than once, the problem might be something broken + * Infinite error recursion might be due to something broken * in a context traceback routine. Abandon them too. We also * abandon attempting to print the error statement (which, if long, * could itself be the source of the recursive failure). */ - if (recursion_depth > 2) + if (in_error_recursion_trouble()) { error_context_stack = NULL; debug_query_string = NULL; @@ -593,18 +608,20 @@ errcode_for_socket_access(void) * it's common code for errmsg(), errdetail(), etc. Must be called inside * a routine that is declared like "const char *fmt, ..." and has an edata * pointer set up. The message is assigned to edata->targetfield, or - * appended to it if appendval is true. + * appended to it if appendval is true. The message is subject to translation + * if translateit is true. * * Note: we pstrdup the buffer rather than just transferring its storage * to the edata field because the buffer might be considerably larger than * really necessary. */ -#define EVALUATE_MESSAGE(targetfield, appendval) \ +#define EVALUATE_MESSAGE(targetfield, appendval, translateit) \ { \ char *fmtbuf; \ StringInfoData buf; \ /* Internationalize the error format string */ \ - fmt = _(fmt); \ + if (translateit) \ + fmt = _(fmt); \ /* Expand %m in format string */ \ fmtbuf = expand_fmt_string(fmt, edata); \ initStringInfo(&buf); \ @@ -651,7 +668,7 @@ errmsg(const char *fmt,...) CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); - EVALUATE_MESSAGE(message, false); + EVALUATE_MESSAGE(message, false, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; @@ -663,9 +680,12 @@ errmsg(const char *fmt,...) * errmsg_internal --- add a primary error message text to the current error * * This is exactly like errmsg() except that strings passed to errmsg_internal - * are customarily left out of the internationalization message dictionary. - * This should be used for "can't happen" cases that are probably not worth - * spending translation effort on. + * are not translated, and are customarily left out of the + * internationalization message dictionary. This should be used for "can't + * happen" cases that are probably not worth spending translation effort on. + * We also use this for certain cases where we *must* not try to translate + * the message because the translation would fail and result in infinite + * error recursion. */ int errmsg_internal(const char *fmt,...) @@ -677,7 +697,7 @@ errmsg_internal(const char *fmt,...) CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); - EVALUATE_MESSAGE(message, false); + EVALUATE_MESSAGE(message, false, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; @@ -698,7 +718,7 @@ errdetail(const char *fmt,...) CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); - EVALUATE_MESSAGE(detail, false); + EVALUATE_MESSAGE(detail, false, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; @@ -719,7 +739,7 @@ errhint(const char *fmt,...) CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); - EVALUATE_MESSAGE(hint, false); + EVALUATE_MESSAGE(hint, false, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; @@ -744,7 +764,7 @@ errcontext(const char *fmt,...) CHECK_STACK_DEPTH(); oldcontext = MemoryContextSwitchTo(ErrorContext); - EVALUATE_MESSAGE(context, true); + EVALUATE_MESSAGE(context, true, true); MemoryContextSwitchTo(oldcontext); recursion_depth--; @@ -922,12 +942,12 @@ elog_finish(int elevel, const char *fmt,...) return; /* nothing to do */ /* - * Format error message just like errmsg(). + * Format error message just like errmsg_internal(). */ recursion_depth++; oldcontext = MemoryContextSwitchTo(ErrorContext); - EVALUATE_MESSAGE(message, false); + EVALUATE_MESSAGE(message, false, false); MemoryContextSwitchTo(oldcontext); recursion_depth--; @@ -1076,7 +1096,9 @@ ReThrowError(ErrorData *edata) /* * Wups, stack not big enough. We treat this as a PANIC condition * because it suggests an infinite loop of errors during error - * recovery. + * recovery. Note that the message is intentionally not localized, + * else failure to convert it to client encoding could cause further + * recursion. */ errordata_stack_depth = -1; /* make room on stack */ ereport(PANIC, (errmsg_internal("ERRORDATA_STACK_SIZE exceeded"))); @@ -2010,6 +2032,10 @@ useful_strerror(int errnum) /* * error_severity --- get localized string representing elevel + * + * Note: in an error recursion situation, we stop localizing the tags + * for ERROR and above. This is necessary because the problem might be + * failure to convert one of these strings to the client encoding. */ static const char * error_severity(int elevel) @@ -2039,13 +2065,22 @@ error_severity(int elevel) prefix = _("WARNING"); break; case ERROR: - prefix = _("ERROR"); + if (in_error_recursion_trouble()) + prefix = "ERROR"; + else + prefix = _("ERROR"); break; case FATAL: - prefix = _("FATAL"); + if (in_error_recursion_trouble()) + prefix = "FATAL"; + else + prefix = _("FATAL"); break; case PANIC: - prefix = _("PANIC"); + if (in_error_recursion_trouble()) + prefix = "PANIC"; + else + prefix = _("PANIC"); break; default: prefix = "???"; |