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

2 files changed

Lines changed: 59 additions & 6 deletions

File tree

‎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_RETURNvoidAssert(constchar* 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
staticvoidAbort(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
#defineNO_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_RETURNvoidAbort();
31+
NO_RETURNvoidAssert(constchar* const (*args)[4]);
2932
voidDumpBacktrace(FILE* fp);
3033

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

5356
#defineABORT() node::Abort()
5457

55-
#if defined(NDEBUG)
56-
# defineASSERT(expression)
57-
# defineCHECK(expression) \
58+
#ifdef __GNUC__
59+
#defineLIKELY(expr) __builtin_expect(!!(expr), 1)
60+
#defineUNLIKELY(expr) __builtin_expect(!!(expr), 0)
61+
#definePRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
62+
#else
63+
#defineLIKELY(expr) expr
64+
#defineUNLIKELY(expr) expr
65+
#definePRETTY_FUNCTION_NAME""
66+
#endif
67+
68+
#defineSTRINGIFY_(x) #x
69+
#defineSTRINGIFY(x) STRINGIFY_(x)
70+
71+
#defineCHECK(expr) \
5872
do { \
59-
if (!(expression)) ABORT(); \
73+
if (UNLIKELY(!(expr))) { \
74+
staticconstchar* 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+
#defineABORTABORT_NO_BACKTRACE
85+
#defineCHECKassert
86+
#endif
87+
88+
#ifdef NDEBUG
89+
#defineASSERT(expr)
6190
#else
62-
# defineASSERT(expression) assert(expression)
63-
# defineCHECK(expression) assert(expression)
91+
#defineASSERT(expr) CHECK(expr)
6492
#endif
6593

6694
#defineASSERT_EQ(a, b) ASSERT((a) == (b))

0 commit comments

Comments
 (0)