mirror of https://github.com/citusdata/citus.git
104 lines
2.1 KiB
C
104 lines
2.1 KiB
C
/*
|
|
* backtrace.c
|
|
*
|
|
* Utilities related to backtrace
|
|
*
|
|
* Copyright (c) Citus Data, Inc.
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
#include "backtrace.h"
|
|
#include "lib/stringinfo.h"
|
|
|
|
#include "distributed/backtrace.h"
|
|
|
|
#define BACKTRACE_HEADER "\nBACKTRACE:\n"
|
|
#define BACKTRACE_SKIP 2
|
|
|
|
static int BacktraceFullCallback(void *data, uintptr_t pc,
|
|
const char *filename, int lineno,
|
|
const char *function);
|
|
|
|
static void BacktraceErrorCallback(void *data, const char *msg, int errnum);
|
|
static void InitBackTrace(void);
|
|
static bool ShouldLogBacktrace(int elevel);
|
|
static char * GenerateBackTrace(int);
|
|
|
|
static struct backtrace_state *backTracestate;
|
|
|
|
static void
|
|
InitBackTrace(void)
|
|
{
|
|
const char *filename = NULL;
|
|
void *data = NULL;
|
|
backTracestate = backtrace_create_state(filename, 0,
|
|
BacktraceErrorCallback, data);
|
|
}
|
|
|
|
|
|
static bool
|
|
ShouldLogBacktrace(int elevel)
|
|
{
|
|
return elevel >= ERROR;
|
|
}
|
|
|
|
|
|
void
|
|
Backtrace(int elevel)
|
|
{
|
|
if (!ShouldLogBacktrace(elevel))
|
|
{
|
|
return;
|
|
}
|
|
errdetail("%s", GenerateBackTrace(BACKTRACE_SKIP));
|
|
}
|
|
|
|
void AssertBacktrace(void) {
|
|
const char * backtrace = GenerateBackTrace(BACKTRACE_SKIP);
|
|
ereport(ERROR, (errmsg("%s", backtrace)));
|
|
}
|
|
|
|
void SignalBacktrace(void) {
|
|
const char * backtrace = GenerateBackTrace(BACKTRACE_SKIP + 1);
|
|
ereport(WARNING, (errmsg("%s", backtrace)));
|
|
}
|
|
|
|
|
|
static char *
|
|
GenerateBackTrace(int skipAmount)
|
|
{
|
|
if (backTracestate == NULL)
|
|
{
|
|
InitBackTrace();
|
|
}
|
|
StringInfo msgWithBacktrace = makeStringInfo();
|
|
|
|
appendStringInfoString(msgWithBacktrace, BACKTRACE_HEADER);
|
|
backtrace_full(backTracestate, skipAmount, BacktraceFullCallback,
|
|
BacktraceErrorCallback, msgWithBacktrace);
|
|
|
|
return msgWithBacktrace->data;
|
|
}
|
|
|
|
|
|
static int
|
|
BacktraceFullCallback(void *data, uintptr_t pc, const char *filename, int lineno,
|
|
const char *function)
|
|
{
|
|
StringInfo str = (StringInfo) data;
|
|
if (function && filename)
|
|
{
|
|
appendStringInfo(str, "%s:%s:%d\n", filename, function, lineno);
|
|
}
|
|
|
|
/* returning 0 means we will continue the backtrace */
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
BacktraceErrorCallback(void *data, const char *msg, int errnum)
|
|
{
|
|
/* currently NO-OP */
|
|
}
|