aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/nls.mk4
-rw-r--r--src/backend/utils/error/elog.c75
-rw-r--r--src/backend/utils/mb/wchar.c17
-rw-r--r--src/include/utils/elog.h3
4 files changed, 73 insertions, 26 deletions
diff --git a/src/backend/nls.mk b/src/backend/nls.mk
index e7da89f005c..471e987d19e 100644
--- a/src/backend/nls.mk
+++ b/src/backend/nls.mk
@@ -1,9 +1,7 @@
-# $PostgreSQL: pgsql/src/backend/nls.mk,v 1.20 2005/10/04 11:14:03 petere Exp $
+# $PostgreSQL: pgsql/src/backend/nls.mk,v 1.20.2.1 2008/10/27 19:37:42 tgl Exp $
CATALOG_NAME := postgres
AVAIL_LANGUAGES := af cs de es fr hr hu it ko nb pt_BR ro ru sk sl sv tr zh_CN zh_TW
GETTEXT_FILES := + gettext-files
-# you can add "elog:2" and "errmsg_internal" to this list if you want to
-# include internal messages in the translation list.
GETTEXT_TRIGGERS:= _ errmsg errdetail errhint errcontext write_stderr yyerror
gettext-files: distprep
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 = "???";
diff --git a/src/backend/utils/mb/wchar.c b/src/backend/utils/mb/wchar.c
index 6e954675393..5e841629d82 100644
--- a/src/backend/utils/mb/wchar.c
+++ b/src/backend/utils/mb/wchar.c
@@ -1,7 +1,7 @@
/*
* conversion functions between pg_wchar and multibyte streams.
* Tatsuo Ishii
- * $PostgreSQL: pgsql/src/backend/utils/mb/wchar.c,v 1.47.2.6 2007/03/26 11:43:09 ishii Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mb/wchar.c,v 1.47.2.7 2008/10/27 19:37:42 tgl Exp $
*
* WIN1250 client encoding updated by Pavel Behal
*
@@ -1379,7 +1379,20 @@ report_untranslatable_char(int src_encoding, int dest_encoding,
for (j = 0; j < jlimit; j++)
p += sprintf(p, "%02x", (unsigned char) mbstr[j]);
- ereport(ERROR,
+ /*
+ * In an error recursion situation, don't try to translate the message.
+ * This gets us out of trouble if the problem is failure to convert
+ * this very message (after translation) to the client encoding.
+ */
+ if (in_error_recursion_trouble())
+ ereport(ERROR,
+ (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
+ errmsg_internal("character 0x%s of encoding \"%s\" has no equivalent in \"%s\"",
+ buf,
+ pg_enc2name_tbl[src_encoding].name,
+ pg_enc2name_tbl[dest_encoding].name)));
+ else
+ ereport(ERROR,
(errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
errmsg("character 0x%s of encoding \"%s\" has no equivalent in \"%s\"",
buf,
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 06b91f05aff..b255253e45c 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.81 2005/10/15 02:49:46 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.81.2.1 2008/10/27 19:37:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -282,6 +282,7 @@ extern int Log_destination;
/* Other exported functions */
extern void DebugFileOpen(void);
extern char *unpack_sql_state(int sql_state);
+extern bool in_error_recursion_trouble(void);
#ifdef HAVE_SYSLOG
extern void set_syslog_parameters(const char *ident, int facility);