42
42
*
43
43
*
44
44
* 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 $
46
46
*
47
47
*-------------------------------------------------------------------------
48
48
*/
@@ -149,6 +149,21 @@ static void write_csvlog(ErrorData *edata);
149
149
static void setup_formatted_log_time (void );
150
150
static void setup_formatted_start_time (void );
151
151
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
+
152
167
/*
153
168
* errstart --- begin an error-reporting cycle
154
169
*
@@ -261,12 +276,12 @@ errstart(int elevel, const char *filename, int lineno,
261
276
MemoryContextReset (ErrorContext );
262
277
263
278
/*
264
- * If we recurse more than once, the problem might be something broken
279
+ * Infinite error recursion might be due to something broken
265
280
* in a context traceback routine. Abandon them too. We also abandon
266
281
* attempting to print the error statement (which, if long, could
267
282
* itself be the source of the recursive failure).
268
283
*/
269
- if (recursion_depth > 2 )
284
+ if (in_error_recursion_trouble () )
270
285
{
271
286
error_context_stack = NULL ;
272
287
debug_query_string = NULL ;
@@ -604,18 +619,20 @@ errcode_for_socket_access(void)
604
619
* it's common code for errmsg(), errdetail(), etc. Must be called inside
605
620
* a routine that is declared like "const char *fmt, ..." and has an edata
606
621
* 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.
608
624
*
609
625
* Note: we pstrdup the buffer rather than just transferring its storage
610
626
* to the edata field because the buffer might be considerably larger than
611
627
* really necessary.
612
628
*/
613
- #define EVALUATE_MESSAGE (targetfield , appendval ) \
629
+ #define EVALUATE_MESSAGE (targetfield , appendval , translateit ) \
614
630
{ \
615
631
char *fmtbuf; \
616
632
StringInfoData buf; \
617
633
/* Internationalize the error format string */ \
618
- fmt = dgettext (edata -> domain , fmt ); \
634
+ if (translateit ) \
635
+ fmt = dgettext (edata -> domain , fmt ); \
619
636
/* Expand %m in format string */ \
620
637
fmtbuf = expand_fmt_string (fmt , edata ); \
621
638
initStringInfo (& buf ); \
@@ -662,7 +679,7 @@ errmsg(const char *fmt,...)
662
679
CHECK_STACK_DEPTH ();
663
680
oldcontext = MemoryContextSwitchTo (ErrorContext );
664
681
665
- EVALUATE_MESSAGE (message , false);
682
+ EVALUATE_MESSAGE (message , false, true );
666
683
667
684
MemoryContextSwitchTo (oldcontext );
668
685
recursion_depth -- ;
@@ -674,9 +691,12 @@ errmsg(const char *fmt,...)
674
691
* errmsg_internal --- add a primary error message text to the current error
675
692
*
676
693
* 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.
680
700
*/
681
701
int
682
702
errmsg_internal (const char * fmt ,...)
@@ -688,7 +708,7 @@ errmsg_internal(const char *fmt,...)
688
708
CHECK_STACK_DEPTH ();
689
709
oldcontext = MemoryContextSwitchTo (ErrorContext );
690
710
691
- EVALUATE_MESSAGE (message , false);
711
+ EVALUATE_MESSAGE (message , false, false );
692
712
693
713
MemoryContextSwitchTo (oldcontext );
694
714
recursion_depth -- ;
@@ -709,7 +729,7 @@ errdetail(const char *fmt,...)
709
729
CHECK_STACK_DEPTH ();
710
730
oldcontext = MemoryContextSwitchTo (ErrorContext );
711
731
712
- EVALUATE_MESSAGE (detail , false);
732
+ EVALUATE_MESSAGE (detail , false, true );
713
733
714
734
MemoryContextSwitchTo (oldcontext );
715
735
recursion_depth -- ;
@@ -730,7 +750,7 @@ errdetail_log(const char *fmt,...)
730
750
CHECK_STACK_DEPTH ();
731
751
oldcontext = MemoryContextSwitchTo (ErrorContext );
732
752
733
- EVALUATE_MESSAGE (detail_log , false);
753
+ EVALUATE_MESSAGE (detail_log , false, true );
734
754
735
755
MemoryContextSwitchTo (oldcontext );
736
756
recursion_depth -- ;
@@ -751,7 +771,7 @@ errhint(const char *fmt,...)
751
771
CHECK_STACK_DEPTH ();
752
772
oldcontext = MemoryContextSwitchTo (ErrorContext );
753
773
754
- EVALUATE_MESSAGE (hint , false);
774
+ EVALUATE_MESSAGE (hint , false, true );
755
775
756
776
MemoryContextSwitchTo (oldcontext );
757
777
recursion_depth -- ;
@@ -776,7 +796,7 @@ errcontext(const char *fmt,...)
776
796
CHECK_STACK_DEPTH ();
777
797
oldcontext = MemoryContextSwitchTo (ErrorContext );
778
798
779
- EVALUATE_MESSAGE (context , true);
799
+ EVALUATE_MESSAGE (context , true, true );
780
800
781
801
MemoryContextSwitchTo (oldcontext );
782
802
recursion_depth -- ;
@@ -956,7 +976,9 @@ elog_start(const char *filename, int lineno, const char *funcname)
956
976
/*
957
977
* Wups, stack not big enough. We treat this as a PANIC condition
958
978
* 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.
960
982
*/
961
983
errordata_stack_depth = -1 ; /* make room on stack */
962
984
ereport (PANIC , (errmsg_internal ("ERRORDATA_STACK_SIZE exceeded" )));
@@ -990,12 +1012,12 @@ elog_finish(int elevel, const char *fmt,...)
990
1012
return ; /* nothing to do */
991
1013
992
1014
/*
993
- * Format error message just like errmsg ().
1015
+ * Format error message just like errmsg_internal ().
994
1016
*/
995
1017
recursion_depth ++ ;
996
1018
oldcontext = MemoryContextSwitchTo (ErrorContext );
997
1019
998
- EVALUATE_MESSAGE (message , false);
1020
+ EVALUATE_MESSAGE (message , false, false );
999
1021
1000
1022
MemoryContextSwitchTo (oldcontext );
1001
1023
recursion_depth -- ;
@@ -2408,6 +2430,10 @@ useful_strerror(int errnum)
2408
2430
2409
2431
/*
2410
2432
* 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.
2411
2437
*/
2412
2438
static const char *
2413
2439
error_severity (int elevel )
@@ -2437,13 +2463,22 @@ error_severity(int elevel)
2437
2463
prefix = _ ("WARNING" );
2438
2464
break ;
2439
2465
case ERROR :
2440
- prefix = _ ("ERROR" );
2466
+ if (in_error_recursion_trouble ())
2467
+ prefix = "ERROR" ;
2468
+ else
2469
+ prefix = _ ("ERROR" );
2441
2470
break ;
2442
2471
case FATAL :
2443
- prefix = _ ("FATAL" );
2472
+ if (in_error_recursion_trouble ())
2473
+ prefix = "FATAL" ;
2474
+ else
2475
+ prefix = _ ("FATAL" );
2444
2476
break ;
2445
2477
case PANIC :
2446
- prefix = _ ("PANIC" );
2478
+ if (in_error_recursion_trouble ())
2479
+ prefix = "PANIC" ;
2480
+ else
2481
+ prefix = _ ("PANIC" );
2447
2482
break ;
2448
2483
default :
2449
2484
prefix = "???" ;
0 commit comments