4242 *
4343 *
4444 * IDENTIFICATION
45- * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.208 2008/10/17 22:56:16 alvherre Exp $
45+ * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.209 2008/10/27 19:37:21 tgl Exp $
4646 *
4747 *-------------------------------------------------------------------------
4848 */
@@ -149,6 +149,21 @@ static void write_csvlog(ErrorData *edata);
149149static void setup_formatted_log_time (void );
150150static void setup_formatted_start_time (void );
151151
152+
153+ /*
154+ * in_error_recursion_trouble --- are we at risk of infinite error recursion?
155+ *
156+ * This function exists to provide common control of various fallback steps
157+ * that we take if we think we are facing infinite error recursion. See the
158+ * callers for details.
159+ */
160+ bool
161+ in_error_recursion_trouble (void )
162+ {
163+ /* Pull the plug if recurse more than once */
164+ return (recursion_depth > 2 );
165+ }
166+
152167/*
153168 * errstart --- begin an error-reporting cycle
154169 *
@@ -261,12 +276,12 @@ errstart(int elevel, const char *filename, int lineno,
261276MemoryContextReset (ErrorContext );
262277
263278/*
264- *If we recurse more than once, the problem might be something broken
279+ *Infinite error recursion might be due to something broken
265280 * in a context traceback routine.Abandon them too. We also abandon
266281 * attempting to print the error statement (which, if long, could
267282 * itself be the source of the recursive failure).
268283 */
269- if (recursion_depth > 2 )
284+ if (in_error_recursion_trouble () )
270285{
271286error_context_stack = NULL ;
272287debug_query_string = NULL ;
@@ -604,18 +619,20 @@ errcode_for_socket_access(void)
604619 * it's common code for errmsg(), errdetail(), etc. Must be called inside
605620 * a routine that is declared like "const char *fmt, ..." and has an edata
606621 * pointer set up.The message is assigned to edata->targetfield, or
607- * appended to it if appendval is true.
622+ * appended to it if appendval is true. The message is subject to translation
623+ * if translateit is true.
608624 *
609625 * Note: we pstrdup the buffer rather than just transferring its storage
610626 * to the edata field because the buffer might be considerably larger than
611627 * really necessary.
612628 */
613- #define EVALUATE_MESSAGE (targetfield ,appendval ) \
629+ #define EVALUATE_MESSAGE (targetfield ,appendval , translateit ) \
614630{ \
615631char *fmtbuf; \
616632StringInfoDatabuf; \
617633/* Internationalize the error format string */ \
618- fmt = dgettext (edata -> domain ,fmt ); \
634+ if (translateit ) \
635+ fmt = dgettext (edata -> domain ,fmt ); \
619636/* Expand %m in format string */ \
620637fmtbuf = expand_fmt_string (fmt ,edata ); \
621638initStringInfo (& buf ); \
@@ -662,7 +679,7 @@ errmsg(const char *fmt,...)
662679CHECK_STACK_DEPTH ();
663680oldcontext = MemoryContextSwitchTo (ErrorContext );
664681
665- EVALUATE_MESSAGE (message , false);
682+ EVALUATE_MESSAGE (message , false, true );
666683
667684MemoryContextSwitchTo (oldcontext );
668685recursion_depth -- ;
@@ -674,9 +691,12 @@ errmsg(const char *fmt,...)
674691 * errmsg_internal --- add a primary error message text to the current error
675692 *
676693 * This is exactly like errmsg() except that strings passed to errmsg_internal
677- * are customarily left out of the internationalization message dictionary.
678- * This should be used for "can't happen" cases that are probably not worth
679- * spending translation effort on.
694+ * are not translated, and are customarily left out of the
695+ * internationalization message dictionary. This should be used for "can't
696+ * happen" cases that are probably not worth spending translation effort on.
697+ * We also use this for certain cases where we *must* not try to translate
698+ * the message because the translation would fail and result in infinite
699+ * error recursion.
680700 */
681701int
682702errmsg_internal (const char * fmt ,...)
@@ -688,7 +708,7 @@ errmsg_internal(const char *fmt,...)
688708CHECK_STACK_DEPTH ();
689709oldcontext = MemoryContextSwitchTo (ErrorContext );
690710
691- EVALUATE_MESSAGE (message , false);
711+ EVALUATE_MESSAGE (message , false, false );
692712
693713MemoryContextSwitchTo (oldcontext );
694714recursion_depth -- ;
@@ -709,7 +729,7 @@ errdetail(const char *fmt,...)
709729CHECK_STACK_DEPTH ();
710730oldcontext = MemoryContextSwitchTo (ErrorContext );
711731
712- EVALUATE_MESSAGE (detail , false);
732+ EVALUATE_MESSAGE (detail , false, true );
713733
714734MemoryContextSwitchTo (oldcontext );
715735recursion_depth -- ;
@@ -730,7 +750,7 @@ errdetail_log(const char *fmt,...)
730750CHECK_STACK_DEPTH ();
731751oldcontext = MemoryContextSwitchTo (ErrorContext );
732752
733- EVALUATE_MESSAGE (detail_log , false);
753+ EVALUATE_MESSAGE (detail_log , false, true );
734754
735755MemoryContextSwitchTo (oldcontext );
736756recursion_depth -- ;
@@ -751,7 +771,7 @@ errhint(const char *fmt,...)
751771CHECK_STACK_DEPTH ();
752772oldcontext = MemoryContextSwitchTo (ErrorContext );
753773
754- EVALUATE_MESSAGE (hint , false);
774+ EVALUATE_MESSAGE (hint , false, true );
755775
756776MemoryContextSwitchTo (oldcontext );
757777recursion_depth -- ;
@@ -776,7 +796,7 @@ errcontext(const char *fmt,...)
776796CHECK_STACK_DEPTH ();
777797oldcontext = MemoryContextSwitchTo (ErrorContext );
778798
779- EVALUATE_MESSAGE (context , true);
799+ EVALUATE_MESSAGE (context , true, true );
780800
781801MemoryContextSwitchTo (oldcontext );
782802recursion_depth -- ;
@@ -956,7 +976,9 @@ elog_start(const char *filename, int lineno, const char *funcname)
956976/*
957977 * Wups, stack not big enough.We treat this as a PANIC condition
958978 * because it suggests an infinite loop of errors during error
959- * recovery.
979+ * recovery. Note that the message is intentionally not localized,
980+ * else failure to convert it to client encoding could cause further
981+ * recursion.
960982 */
961983errordata_stack_depth = -1 ;/* make room on stack */
962984ereport (PANIC , (errmsg_internal ("ERRORDATA_STACK_SIZE exceeded" )));
@@ -990,12 +1012,12 @@ elog_finish(int elevel, const char *fmt,...)
9901012return ;/* nothing to do */
9911013
9921014/*
993- * Format error message just likeerrmsg ().
1015+ * Format error message just likeerrmsg_internal ().
9941016 */
9951017recursion_depth ++ ;
9961018oldcontext = MemoryContextSwitchTo (ErrorContext );
9971019
998- EVALUATE_MESSAGE (message , false);
1020+ EVALUATE_MESSAGE (message , false, false );
9991021
10001022MemoryContextSwitchTo (oldcontext );
10011023recursion_depth -- ;
@@ -2408,6 +2430,10 @@ useful_strerror(int errnum)
24082430
24092431/*
24102432 * error_severity --- get localized string representing elevel
2433+ *
2434+ * Note: in an error recursion situation, we stop localizing the tags
2435+ * for ERROR and above. This is necessary because the problem might be
2436+ * failure to convert one of these strings to the client encoding.
24112437 */
24122438static const char *
24132439error_severity (int elevel )
@@ -2437,13 +2463,22 @@ error_severity(int elevel)
24372463prefix = _ ("WARNING" );
24382464break ;
24392465case ERROR :
2440- prefix = _ ("ERROR" );
2466+ if (in_error_recursion_trouble ())
2467+ prefix = "ERROR" ;
2468+ else
2469+ prefix = _ ("ERROR" );
24412470break ;
24422471case FATAL :
2443- prefix = _ ("FATAL" );
2472+ if (in_error_recursion_trouble ())
2473+ prefix = "FATAL" ;
2474+ else
2475+ prefix = _ ("FATAL" );
24442476break ;
24452477case PANIC :
2446- prefix = _ ("PANIC" );
2478+ if (in_error_recursion_trouble ())
2479+ prefix = "PANIC" ;
2480+ else
2481+ prefix = _ ("PANIC" );
24472482break ;
24482483default :
24492484prefix = "???" ;