Skip to content

Commit cf1f528

Browse files
report: catch internal segfaults
`--diagnostic-report-on-fatalerror` does not capture internal segfaults at present, instead limited to only faults that are detected by the Node / v8. libuv's signal handler deliveres result asynchronously which does not help for SIGSEGV as: i) the synchronous sequence restarts the failing code, ii) due to i) the callback is never delivered to the consumer. Install a SIGSEGV handler in Node and follow the sequence of fatalerror handling, as of now at least under report. Fixes: nodejs#25762
1 parent d6a32cf commit cf1f528

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

src/node_errors.cc

+15
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,21 @@ void PrintErrorString(const char* format, ...) {
306306
ABORT();
307307
}
308308

309+
#ifndef _WIN32
310+
void OnSIGSEGV(int signo) {
311+
uv_tty_reset_mode();
312+
#ifdef __FreeBSD__
313+
// FreeBSD has a nasty bug, see RegisterSignalHandler for details
314+
struct sigaction sa;
315+
memset(&sa, 0, sizeof(sa));
316+
sa.sa_handler = SIG_DFL;
317+
CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
318+
#endif
319+
CHECK_EQ(signo, SIGSEGV);
320+
OnFatalError(__func__, "caught internal error.");
321+
}
322+
#endif // _WIN32
323+
309324
void OnFatalError(const char* location, const char* message) {
310325
if (location) {
311326
PrintErrorString("FATAL ERROR: %s %s\n", location, message);

src/node_errors.h

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ void AppendExceptionLine(Environment* env,
2222

2323
[[noreturn]] void FatalError(const char* location, const char* message);
2424
void OnFatalError(const char* location, const char* message);
25+
#ifndef _WIN32
26+
void OnSIGSEGV(int signo);
27+
#endif // _WIN32
2528

2629
// Like a `TryCatch` but exits the process if an exception was caught.
2730
class FatalTryCatch : public v8::TryCatch {

src/node_report_module.cc

+15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "env.h"
2+
#include "node.h"
23
#include "node_errors.h"
34
#include "node_internals.h"
45
#include "node_options.h"
@@ -262,6 +263,20 @@ static void Initialize(Local<Object> exports,
262263
env->SetMethod(exports, "onUserSignal", OnUserSignal);
263264
env->SetMethod(exports, "syncConfig", SyncConfig);
264265

266+
// Libuv based signal handling does not help internal segfaults,
267+
// as synchronously delivered signals are handled asynchronously
268+
// in libuv at present, which Node.js is unable to effectively
269+
// consume. So install one of our own; make sure reset tty mode
270+
// and exit; do not return gracefully that causes fault context
271+
// to be invoked again.
272+
// TODO(gireeshpunathil) decide what to do with asynchronous
273+
// sigsegv handling - handle separately, or merge with this one.
274+
#ifndef _WIN32
275+
if (options->report_on_fatalerror) {
276+
node::RegisterSignalHandler(SIGSEGV, node::OnSIGSEGV, true);
277+
}
278+
#endif // _WIN32
279+
265280
// TODO(gireeshpunathil) if we are retaining this flag,
266281
// insert more verbose information at vital control flow
267282
// points. Right now, it is only this one.

0 commit comments

Comments
 (0)