Browse Source

src: print backtrace on failed CHECK/ASSERT

Print a C backtrace on fatal errors to make it easier to debug issues.

PR-URL: https://github.com/nodejs/node/pull/6734
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
v6.x
Ben Noordhuis 9 years ago
committed by Jeremiah Senkpiel
parent
commit
57cc4e3071
  1. 25
      src/node.cc
  2. 40
      src/util.h

25
src/node.cc

@ -1795,6 +1795,31 @@ NO_RETURN void Abort() {
} }
NO_RETURN void Assert(const char* const (*args)[4]) {
auto filename = (*args)[0];
auto linenum = (*args)[1];
auto message = (*args)[2];
auto function = (*args)[3];
char exepath[256];
size_t exepath_size = sizeof(exepath);
if (uv_exepath(exepath, &exepath_size))
snprintf(exepath, sizeof(exepath), "node");
char pid[12] = {0};
#ifndef _WIN32
snprintf(pid, sizeof(pid), "[%u]", getpid());
#endif
fprintf(stderr, "%s%s: %s:%s:%s%s Assertion `%s' failed.\n",
exepath, pid, filename, linenum,
function, *function ? ":" : "", message);
fflush(stderr);
Abort();
}
static void Abort(const FunctionCallbackInfo<Value>& args) { static void Abort(const FunctionCallbackInfo<Value>& args) {
Abort(); Abort();
} }

40
src/util.h

@ -25,7 +25,10 @@ namespace node {
#define NO_RETURN #define NO_RETURN
#endif #endif
// The slightly odd function signature for Assert() is to ease
// instruction cache pressure in calls from ASSERT and CHECK.
NO_RETURN void Abort(); NO_RETURN void Abort();
NO_RETURN void Assert(const char* const (*args)[4]);
void DumpBacktrace(FILE* fp); void DumpBacktrace(FILE* fp);
#ifdef __APPLE__ #ifdef __APPLE__
@ -52,15 +55,40 @@ template <typename T> using remove_reference = std::remove_reference<T>;
#define ABORT() node::Abort() #define ABORT() node::Abort()
#if defined(NDEBUG) #ifdef __GNUC__
# define ASSERT(expression) #define LIKELY(expr) __builtin_expect(!!(expr), 1)
# define CHECK(expression) \ #define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
#else
#define LIKELY(expr) expr
#define UNLIKELY(expr) expr
#define PRETTY_FUNCTION_NAME ""
#endif
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#define CHECK(expr) \
do { \ do { \
if (!(expression)) ABORT(); \ if (UNLIKELY(!(expr))) { \
static const char* const args[] = { __FILE__, STRINGIFY(__LINE__), \
#expr, PRETTY_FUNCTION_NAME }; \
node::Assert(&args); \
} \
} while (0) } while (0)
// FIXME(bnoordhuis) cctests don't link in node::Abort() and node::Assert().
#ifdef GTEST_DONT_DEFINE_ASSERT_EQ
#undef ABORT
#undef CHECK
#define ABORT ABORT_NO_BACKTRACE
#define CHECK assert
#endif
#ifdef NDEBUG
#define ASSERT(expr)
#else #else
# define ASSERT(expression) assert(expression) #define ASSERT(expr) CHECK(expr)
# define CHECK(expression) assert(expression)
#endif #endif
#define ASSERT_EQ(a, b) ASSERT((a) == (b)) #define ASSERT_EQ(a, b) ASSERT((a) == (b))

Loading…
Cancel
Save