Skip to content

Commit 0124934

Browse files
committed
Allow specifying a callback. Don't write files.
1 parent af7c153 commit 0124934

File tree

2 files changed

+48
-25
lines changed

2 files changed

+48
-25
lines changed

binding.gyp

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
"src/segfault-handler.cpp"
77
],
88
"defines": [ "DEBUG", "_DEBUG" ],
9-
"cflags": [ "-O0" ],
9+
"cflags": [ "-O0", "-g" ],
1010
"xcode_settings": {
11-
"OTHER_CFLAGS": [ "-O0" ]
11+
"OTHER_CFLAGS": [ "-O0", "-g"],
12+
"OTHER_LFLAGS": [ "-O0", "-g"]
1213
}
1314
}
1415
]

src/segfault-handler.cpp

+45-23
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,37 @@ using namespace node;
1818

1919
#define STDERR_FD 2
2020

21+
static Persistent<Function> callback;
22+
static bool handlersSet = false;
23+
2124
static void segfault_handler(int sig, siginfo_t *si, void *unused) {
2225
void *array[32]; // Array to store backtrace symbols
2326
size_t size; // To store the size of the stack backtrace
2427
char sbuff[128];
2528
int n; // chars written to buffer
26-
int fd;
27-
time_t now;
2829
int pid;
2930

30-
// Construct a filename
31-
time(&now);
3231
pid = getpid();
33-
snprintf(sbuff, sizeof(sbuff), "stacktrace-%d-%d.log", (int)now, pid );
3432

35-
// Open the File
36-
fd = open(sbuff, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IRGRP | S_IROTH);
37-
// Write the header line
38-
n = snprintf(sbuff, sizeof(sbuff), "PID %d received SIGSEGV for address: 0x%lx\n", pid, (long) si->si_addr);
39-
if(fd > 0) write(fd, sbuff, n);
33+
n = snprintf(sbuff, sizeof(sbuff), "PID %d received SIGSEGV/SIGBUS (%i) for address: 0x%lx\n", pid, si->si_signo, (long)si->si_addr);
4034
write(STDERR_FD, sbuff, n);
4135

42-
// Write the Backtrace
4336
size = backtrace(array, 32);
44-
if(fd > 0) backtrace_symbols_fd(array, size, fd);
4537
backtrace_symbols_fd(array, size, STDERR_FD);
4638

47-
// Exit violently
48-
close(fd);
49-
exit(-1);
39+
if (!callback.IsEmpty()) {
40+
char **stack = backtrace_symbols(array, size);
41+
Local<Array> argStack = Local<Array>::New(Array::New(size));
42+
for (size_t i = 0; i < size; i++) {
43+
argStack->Set(i, String::New(stack[i]));
44+
}
45+
Local<Value> argv[3] = {argStack, Local<Value>::New(Number::New(si->si_signo)), Local<Value>::New(Number::New((long)si->si_addr))};
46+
callback->Call(Context::GetCurrent()->Global(), 3, argv);
47+
free(stack);
48+
}
49+
50+
// Re-send the signal, this time a default handler will be called
51+
kill(pid, si->si_signo);
5052
}
5153

5254
// create some stack frames to inspect from CauseSegfault
@@ -62,7 +64,6 @@ void segfault_stack_frame_1()
6264
int *foo = (int*)1;
6365
printf("NodeSegfaultHandlerNative: about to dereference NULL (will cause a SIGSEGV)\n");
6466
*foo = 78; // trigger a SIGSEGV
65-
6667
}
6768

6869
__attribute__ ((noinline))
@@ -80,13 +81,34 @@ Handle<Value> CauseSegfault(const Arguments& args) {
8081
}
8182

8283
Handle<Value> RegisterHandler(const Arguments& args) {
83-
struct sigaction sa;
84-
memset(&sa, 0, sizeof(struct sigaction));
85-
sigemptyset(&sa.sa_mask);
86-
sa.sa_sigaction = segfault_handler;
87-
sa.sa_flags = SA_SIGINFO;
88-
sigaction(SIGSEGV, &sa, NULL);
89-
return Undefined();
84+
HandleScope scope;
85+
86+
if (args.Length() > 0) {
87+
if (!args[0]->IsFunction()) {
88+
ThrowException(Exception::TypeError(String::New("Invalid callback argument")));
89+
return scope.Close(Undefined());
90+
}
91+
92+
if (!callback.IsEmpty()) {
93+
callback.Dispose();
94+
callback.Clear();
95+
}
96+
callback = Persistent<Function>::New(Handle<Function>::Cast(args[0]));
97+
}
98+
99+
// Set our handler only once
100+
if (!handlersSet) {
101+
struct sigaction sa;
102+
memset(&sa, 0, sizeof(struct sigaction));
103+
sigemptyset(&sa.sa_mask);
104+
sa.sa_sigaction = segfault_handler;
105+
sa.sa_flags = SA_SIGINFO | SA_RESETHAND; // We set SA_RESETHAND so that our handler is called only once
106+
sigaction(SIGSEGV, &sa, NULL);
107+
sigaction(SIGBUS, &sa, NULL);
108+
handlersSet = true;
109+
}
110+
111+
return scope.Close(Undefined());
90112
}
91113

92114
extern "C" {

0 commit comments

Comments
 (0)