Skip to content

Commit fa3e6e7

Browse files
committed
Allow user to register handlers for signals other than SIGSEGV
In my particular case I'm trying to hunt down a SIGABRT, but why not be general and allow for other unexpected uses. (The code comments actually mention that SIGILL is often generated by a deliberate dereference of a NULL pointer, for instance.)
1 parent 7fb9fe3 commit fa3e6e7

File tree

2 files changed

+67
-6
lines changed

2 files changed

+67
-6
lines changed

README.md

+13
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,19 @@ Now you can start debugging using tools like "objdump -dS module.node" to try an
5555

5656
Cheers, enjoy. And happy hunting.
5757

58+
# Looking at other signals.
59+
60+
On OSX and Linux you can also register handlers for other (presumably
61+
unexpected) signals by specifying an extra parameter:
62+
```javascript
63+
64+
var SegfaultHandler = require('segfault-handler');
65+
66+
SegfaultHandler.registerHandler(SegfaultHandler.SIGSEGV);
67+
SegfaultHandler.registerHandler("crash.log", SegfaultHandler.SIGABRT);
68+
```
69+
The last logfile name registered takes effect.
70+
5871
# License
5972

6073
We are using the callstack walker project from [Walking the Callstack](http://www.codeproject.com/Articles/11132/Walking-the-callstack).

src/segfault-handler.cpp

+54-6
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ NAN_METHOD(CauseSegfault) {
159159
}
160160

161161
NAN_METHOD(RegisterHandler) {
162+
int sigArg = -1, signal = SIGSEGV;
162163
// if passed a path, we'll set the log name to whatever is provided
163-
// this will allow users to use the logs in error reporting without redirecting
164-
// sdterr
165-
logPath[0] = '\0';
166-
if (info.Length() == 1) {
164+
// this will allow users to use the logs in error reporting without
165+
// redirecting stderr
166+
if (info.Length() >= 1) {
167167
if (info[0]->IsString()) {
168168
v8::String::Utf8Value utf8Value(info[0]->ToString());
169169

@@ -172,11 +172,19 @@ NAN_METHOD(RegisterHandler) {
172172
len = len > BUFF_SIZE ? BUFF_SIZE : len;
173173

174174
strncpy(logPath, *utf8Value, len);
175-
logPath[127] = '\0';
175+
logPath[BUFF_SIZE-1] = '\0';
176+
if (info.Length() >= 2 && info[1]->IsNumber()) {
177+
sigArg = 1;
178+
}
179+
} else if (info[0]->IsNumber()) {
180+
sigArg = 0;
176181
} else {
177182
return ThrowError("First argument must be a string.");
178183
}
179184
}
185+
if (sigArg >= 0) {
186+
signal = Nan::To<int32_t>(info[sigArg]).FromMaybe(SIGSEGV);
187+
}
180188

181189
#ifdef _WIN32
182190
AddVectoredExceptionHandler(1, segfault_handler);
@@ -186,14 +194,54 @@ NAN_METHOD(RegisterHandler) {
186194
sigemptyset(&sa.sa_mask);
187195
sa.sa_sigaction = segfault_handler;
188196
sa.sa_flags = SA_SIGINFO;
189-
sigaction(SIGSEGV, &sa, NULL);
197+
sigaction(signal, &sa, NULL);
190198
#endif
191199
}
192200

193201
extern "C" {
194202
NAN_MODULE_INIT(init) {
203+
logPath[0] = '\0';
195204
Nan::SetMethod(target, "registerHandler", RegisterHandler);
196205
Nan::SetMethod(target, "causeSegfault", CauseSegfault);
206+
// Export signal names and values.
207+
#define EXPORT(signal) \
208+
Nan::ForceSet(target, Nan::New<v8::String>(#signal).ToLocalChecked(), Nan::New(signal), v8::ReadOnly)
209+
// Not all of these make sense to register handlers on, but we'll let
210+
// the user decide that. Presumably you're using this package because
211+
// you're seeing an unexpected signal of some sort. Hopefully it's
212+
// included below. (And if not, just pass it by integer value.)
213+
EXPORT(SIGHUP);
214+
EXPORT(SIGINT);
215+
EXPORT(SIGQUIT);
216+
EXPORT(SIGILL);
217+
EXPORT(SIGTRAP);
218+
EXPORT(SIGABRT);
219+
EXPORT(SIGBUS);
220+
EXPORT(SIGFPE);
221+
EXPORT(SIGKILL);
222+
EXPORT(SIGUSR1);
223+
EXPORT(SIGUSR2);
224+
EXPORT(SIGSEGV);
225+
EXPORT(SIGUSR2);
226+
EXPORT(SIGPIPE);
227+
EXPORT(SIGALRM);
228+
EXPORT(SIGTERM);
229+
EXPORT(SIGSTKFLT);
230+
EXPORT(SIGCHLD);
231+
EXPORT(SIGCONT);
232+
EXPORT(SIGSTOP);
233+
EXPORT(SIGTSTP);
234+
EXPORT(SIGTTIN);
235+
EXPORT(SIGTTOU);
236+
EXPORT(SIGURG);
237+
EXPORT(SIGXCPU);
238+
EXPORT(SIGXFSZ);
239+
EXPORT(SIGVTALRM);
240+
EXPORT(SIGPROF);
241+
EXPORT(SIGWINCH);
242+
EXPORT(SIGIO);
243+
EXPORT(SIGPWR);
244+
EXPORT(SIGSYS);
197245
}
198246

199247
NODE_MODULE(segfault_handler, init)

0 commit comments

Comments
 (0)