mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Add backtrace support for error reporting
Add some support for automatically showing backtraces in certain error situations in the server. Backtraces are shown on assertion failure; also, a new setting backtrace_functions can be set to a list of C function names, and all ereport()s and elog()s from the mentioned functions will have backtraces generated. Finally, the function errbacktrace() can be manually added to an ereport() call to generate a backtrace for that call. Authors: Peter Eisentraut, Álvaro Herrera Discussion: https://postgr.es/m//5f48cb47-bf1e-05b6-7aae-3bf2cd01586d@2ndquadrant.com Discussion: https://postgr.es/m/CAMsr+YGL+yfWE=JvbUbnpWtrRZNey7hJ07+zT4bYJdVp4Szdrg@mail.gmail.com
This commit is contained in:
@ -201,6 +201,8 @@ static bool check_cluster_name(char **newval, void **extra, GucSource source);
|
||||
static const char *show_unix_socket_permissions(void);
|
||||
static const char *show_log_file_mode(void);
|
||||
static const char *show_data_directory_mode(void);
|
||||
static bool check_backtrace_functions(char **newval, void **extra, GucSource source);
|
||||
static void assign_backtrace_functions(const char *newval, void *extra);
|
||||
static bool check_recovery_target_timeline(char **newval, void **extra, GucSource source);
|
||||
static void assign_recovery_target_timeline(const char *newval, void *extra);
|
||||
static bool check_recovery_target(char **newval, void **extra, GucSource source);
|
||||
@ -515,6 +517,8 @@ int log_temp_files = -1;
|
||||
double log_statement_sample_rate = 1.0;
|
||||
double log_xact_sample_rate = 0;
|
||||
int trace_recovery_messages = LOG;
|
||||
char *backtrace_functions;
|
||||
char *backtrace_symbol_list;
|
||||
|
||||
int temp_file_limit = -1;
|
||||
|
||||
@ -4224,6 +4228,17 @@ static struct config_string ConfigureNamesString[] =
|
||||
NULL, NULL, NULL
|
||||
},
|
||||
|
||||
{
|
||||
{"backtrace_functions", PGC_SUSET, DEVELOPER_OPTIONS,
|
||||
gettext_noop("Log backtrace for errors in these functions."),
|
||||
NULL,
|
||||
GUC_NOT_IN_SAMPLE
|
||||
},
|
||||
&backtrace_functions,
|
||||
"",
|
||||
check_backtrace_functions, assign_backtrace_functions, NULL
|
||||
},
|
||||
|
||||
/* End-of-list marker */
|
||||
{
|
||||
{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
|
||||
@ -11487,6 +11502,76 @@ show_data_directory_mode(void)
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* We split the input string, where commas separate function names
|
||||
* and certain whitespace chars are ignored, into a \0-separated (and
|
||||
* \0\0-terminated) list of function names. This formulation allows
|
||||
* easy scanning when an error is thrown while avoiding the use of
|
||||
* non-reentrant strtok(), as well as keeping the output data in a
|
||||
* single palloc() chunk.
|
||||
*/
|
||||
static bool
|
||||
check_backtrace_functions(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
int newvallen = strlen(*newval);
|
||||
char *someval;
|
||||
int validlen;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
/*
|
||||
* Allow characters that can be C identifiers and commas as separators, as
|
||||
* well as some whitespace for readability.
|
||||
*/
|
||||
validlen = strspn(*newval,
|
||||
"0123456789_"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
", \n\t");
|
||||
if (validlen != newvallen)
|
||||
{
|
||||
GUC_check_errdetail("invalid character");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*newval[0] == '\0')
|
||||
{
|
||||
*extra = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate space for the output and create the copy. We could discount
|
||||
* whitespace chars to save some memory, but it doesn't seem worth the
|
||||
* trouble.
|
||||
*/
|
||||
someval = guc_malloc(ERROR, newvallen + 1 + 1);
|
||||
for (i = 0, j = 0; i < newvallen; i++)
|
||||
{
|
||||
if ((*newval)[i] == ',')
|
||||
someval[j++] = '\0'; /* next item */
|
||||
else if ((*newval)[i] == ' ' ||
|
||||
(*newval)[i] == '\n' ||
|
||||
(*newval)[i] == '\t')
|
||||
; /* ignore these */
|
||||
else
|
||||
someval[j++] = (*newval)[i]; /* copy anything else */
|
||||
}
|
||||
|
||||
/* two \0s end the setting */
|
||||
someval[j] = '\0';
|
||||
someval[j + 1] = '\0';
|
||||
|
||||
*extra = someval;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
assign_backtrace_functions(const char *newval, void *extra)
|
||||
{
|
||||
backtrace_symbol_list = (char *) extra;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_recovery_target_timeline(char **newval, void **extra, GucSource source)
|
||||
{
|
||||
|
Reference in New Issue
Block a user