Skip to content

Commit 57cc4e3

Browse files
bnoordhuisFishrock123
authored andcommitted
src: print backtrace on failed CHECK/ASSERT
Print a C backtrace on fatal errors to make it easier to debug issues. PR-URL: #6734 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent b8919b1 commit 57cc4e3

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

src/node.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,31 @@ NO_RETURN void Abort() {
17951795
}
17961796

17971797

1798+
NO_RETURN void Assert(const char* const (*args)[4]) {
1799+
auto filename = (*args)[0];
1800+
auto linenum = (*args)[1];
1801+
auto message = (*args)[2];
1802+
auto function = (*args)[3];
1803+
1804+
char exepath[256];
1805+
size_t exepath_size = sizeof(exepath);
1806+
if (uv_exepath(exepath, &exepath_size))
1807+
snprintf(exepath, sizeof(exepath), "node");
1808+
1809+
char pid[12] = {0};
1810+
#ifndef _WIN32
1811+
snprintf(pid, sizeof(pid), "[%u]", getpid());
1812+
#endif
1813+
1814+
fprintf(stderr, "%s%s: %s:%s:%s%s Assertion `%s' failed.\n",
1815+
exepath, pid, filename, linenum,
1816+
function, *function ? ":" : "", message);
1817+
fflush(stderr);
1818+
1819+
Abort();
1820+
}
1821+
1822+
17981823
static void Abort(const FunctionCallbackInfo<Value>& args) {
17991824
Abort();
18001825
}

src/util.h

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ namespace node {
2525
#define NO_RETURN
2626
#endif
2727

28+
// The slightly odd function signature for Assert() is to ease
29+
// instruction cache pressure in calls from ASSERT and CHECK.
2830
NO_RETURN void Abort();
31+
NO_RETURN void Assert(const char* const (*args)[4]);
2932
void DumpBacktrace(FILE* fp);
3033

3134
#ifdef __APPLE__
@@ -52,15 +55,40 @@ template <typename T> using remove_reference = std::remove_reference<T>;
5255

5356
#define ABORT() node::Abort()
5457

55-
#if defined(NDEBUG)
56-
# define ASSERT(expression)
57-
# define CHECK(expression) \
58+
#ifdef __GNUC__
59+
#define LIKELY(expr) __builtin_expect(!!(expr), 1)
60+
#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
61+
#define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
62+
#else
63+
#define LIKELY(expr) expr
64+
#define UNLIKELY(expr) expr
65+
#define PRETTY_FUNCTION_NAME ""
66+
#endif
67+
68+
#define STRINGIFY_(x) #x
69+
#define STRINGIFY(x) STRINGIFY_(x)
70+
71+
#define CHECK(expr) \
5872
do { \
59-
if (!(expression)) ABORT(); \
73+
if (UNLIKELY(!(expr))) { \
74+
static const char* const args[] = { __FILE__, STRINGIFY(__LINE__), \
75+
#expr, PRETTY_FUNCTION_NAME }; \
76+
node::Assert(&args); \
77+
} \
6078
} while (0)
79+
80+
// FIXME(bnoordhuis) cctests don't link in node::Abort() and node::Assert().
81+
#ifdef GTEST_DONT_DEFINE_ASSERT_EQ
82+
#undef ABORT
83+
#undef CHECK
84+
#define ABORT ABORT_NO_BACKTRACE
85+
#define CHECK assert
86+
#endif
87+
88+
#ifdef NDEBUG
89+
#define ASSERT(expr)
6190
#else
62-
# define ASSERT(expression) assert(expression)
63-
# define CHECK(expression) assert(expression)
91+
#define ASSERT(expr) CHECK(expr)
6492
#endif
6593

6694
#define ASSERT_EQ(a, b) ASSERT((a) == (b))

0 commit comments

Comments
 (0)