@ -42,7 +42,7 @@
*
*
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / utils / error / elog . c , v 1.167 .2 .6 2008 / 07 / 08 22 : 18 : 0 2 tgl Exp $
* $ PostgreSQL : pgsql / src / backend / utils / error / elog . c , v 1.167 .2 .7 2008 / 10 / 27 19 : 37 : 4 2 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,17 +608,19 @@ 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 */ \
if ( translateit ) \
fmt = _ ( fmt ) ; \
/* Expand %m in format string */ \
fmtbuf = expand_fmt_string ( fmt , edata ) ; \
@ -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,12 +2065,21 @@ error_severity(int elevel)
prefix = _ ( " WARNING " ) ;
break ;
case ERROR :
if ( in_error_recursion_trouble ( ) )
prefix = " ERROR " ;
else
prefix = _ ( " ERROR " ) ;
break ;
case FATAL :
if ( in_error_recursion_trouble ( ) )
prefix = " FATAL " ;
else
prefix = _ ( " FATAL " ) ;
break ;
case PANIC :
if ( in_error_recursion_trouble ( ) )
prefix = " PANIC " ;
else
prefix = _ ( " PANIC " ) ;
break ;
default :