@ -42,7 +42,7 @@
*
*
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / utils / error / elog . c , v 1.208 2008 / 10 / 17 22 : 56 : 16 alvherre Exp $
* $ PostgreSQL : pgsql / src / backend / utils / error / elog . c , v 1.209 2008 / 10 / 27 19 : 37 : 21 tgl Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
@ -149,6 +149,21 @@ static void write_csvlog(ErrorData *edata);
static void setup_formatted_log_time ( void ) ;
static void setup_formatted_start_time ( void ) ;
/*
* 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
*
@ -261,12 +276,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 ;
@ -604,18 +619,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 = dgettext ( edata - > domain , fmt ) ; \
if ( translateit ) \
fmt = dgettext ( edata - > domain , fmt ) ; \
/* Expand %m in format string */ \
fmtbuf = expand_fmt_string ( fmt , edata ) ; \
initStringInfo ( & buf ) ; \
@ -662,7 +679,7 @@ errmsg(const char *fmt,...)
CHECK_STACK_DEPTH ( ) ;
oldcontext = MemoryContextSwitchTo ( ErrorContext ) ;
EVALUATE_MESSAGE ( message , false ) ;
EVALUATE_MESSAGE ( message , false , true ) ;
MemoryContextSwitchTo ( oldcontext ) ;
recursion_depth - - ;
@ -674,9 +691,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 , . . . )
@ -688,7 +708,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 - - ;
@ -709,7 +729,7 @@ errdetail(const char *fmt,...)
CHECK_STACK_DEPTH ( ) ;
oldcontext = MemoryContextSwitchTo ( ErrorContext ) ;
EVALUATE_MESSAGE ( detail , false ) ;
EVALUATE_MESSAGE ( detail , false , true ) ;
MemoryContextSwitchTo ( oldcontext ) ;
recursion_depth - - ;
@ -730,7 +750,7 @@ errdetail_log(const char *fmt,...)
CHECK_STACK_DEPTH ( ) ;
oldcontext = MemoryContextSwitchTo ( ErrorContext ) ;
EVALUATE_MESSAGE ( detail_log , false ) ;
EVALUATE_MESSAGE ( detail_log , false , true ) ;
MemoryContextSwitchTo ( oldcontext ) ;
recursion_depth - - ;
@ -751,7 +771,7 @@ errhint(const char *fmt,...)
CHECK_STACK_DEPTH ( ) ;
oldcontext = MemoryContextSwitchTo ( ErrorContext ) ;
EVALUATE_MESSAGE ( hint , false ) ;
EVALUATE_MESSAGE ( hint , false , true ) ;
MemoryContextSwitchTo ( oldcontext ) ;
recursion_depth - - ;
@ -776,7 +796,7 @@ errcontext(const char *fmt,...)
CHECK_STACK_DEPTH ( ) ;
oldcontext = MemoryContextSwitchTo ( ErrorContext ) ;
EVALUATE_MESSAGE ( context , true ) ;
EVALUATE_MESSAGE ( context , true , true ) ;
MemoryContextSwitchTo ( oldcontext ) ;
recursion_depth - - ;
@ -956,7 +976,9 @@ elog_start(const char *filename, int lineno, const char *funcname)
/*
* 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 " ) ) ) ;
@ -990,12 +1012,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 - - ;
@ -2408,6 +2430,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 )
@ -2437,13 +2463,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 = " ??? " ;