66#include < fcntl.h>
77#include < sys/types.h>
88#include < sys/stat.h>
9- #include < assert.h>
109#include < stdarg.h>
1110#include < node.h>
12- #include < time.h>
1311#include < node_buffer.h>
1412#include < node_object_wrap.h>
1513#include < v8-debug.h>
14+
15+ #ifdef __APPLE__
16+ #define UNW_LOCAL_ONLY
17+ #include < libunwind.h>
18+ #endif
19+
1620using namespace v8 ;
1721using namespace node ;
1822
@@ -21,30 +25,86 @@ using namespace node;
2125static Persistent<Function> callback;
2226static bool handlersSet = false ;
2327
24- static void segfault_handler (int sig, siginfo_t *si, void *unused) {
25- void *array[32 ]; // Array to store backtrace symbols
26- size_t size; // To store the size of the stack backtrace
27- char sbuff[128 ];
28- int n; // chars written to buffer
29- int pid;
28+ static void emptyCallback (siginfo_t *si) {
29+ Local<Array> argStack = Local<Array>::New (Array::New (0 ));
30+ Local<Value> argv[3 ] = {argStack, Local<Value>::New (Number::New (si->si_signo )), Local<Value>::New (Number::New ((unsigned long long )si->si_addr ))};
31+ callback->Call (Context::GetCurrent ()->Global (), 3 , argv);
32+ }
3033
31- pid = getpid ();
34+ static void segfaultHandler (int sig, siginfo_t *si, void *unused) {
35+ char buffer[1024 * 10 ];
3236
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 );
34- write (STDERR_FD, sbuff, n);
37+ int pid = getpid ();
3538
36- size = backtrace (array, 32 );
37- backtrace_symbols_fd (array, size, STDERR_FD );
39+ snprintf (buffer, sizeof (buffer), " PID %d received SIGSEGV/SIGBUS (%i) for address: 0x%llx \n " , pid, si-> si_signo , ( unsigned long long )si-> si_addr );
40+ write (STDERR_FD, buffer, strlen (buffer) );
3841
3942 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]));
43+ void *stack[32 ];
44+ size_t stackSize;
45+
46+ stackSize = backtrace (stack, 32 );
47+
48+ if (stackSize > 0 ) {
49+ char **stackSymbols = backtrace_symbols (stack, stackSize);
50+ Local<Array> argStack = Local<Array>::New (Array::New (stackSize));
51+ for (size_t i = 0 ; i < stackSize; i++) {
52+ argStack->Set (i, String::New (stackSymbols[i]));
53+ }
54+ free (stackSymbols);
55+
56+ Local<Value> argv[3 ] = {argStack, Local<Value>::New (Number::New (si->si_signo )), Local<Value>::New (Number::New ((unsigned long long )si->si_addr ))};
57+ callback->Call (Context::GetCurrent ()->Global (), 3 , argv);
58+ }
59+ else {
60+ #ifdef __APPLE__
61+ unw_cursor_t cursor;
62+ unw_context_t context;
63+ unw_word_t pc;
64+
65+ unw_getcontext (&context);
66+ unw_init_local (&cursor, &context);
67+
68+ snprintf (buffer, sizeof (buffer), " atos -p %i" , pid);
69+
70+ int frames = 0 ;
71+ while (unw_step (&cursor) > 0 ) {
72+ frames++;
73+ unw_get_reg (&cursor, UNW_REG_IP, &pc);
74+ int len = strlen (buffer);
75+ snprintf (buffer + len, sizeof (buffer) - len, " 0x%llx" , pc);
76+ }
77+
78+ if (frames > 0 ) {
79+ FILE* program = popen (buffer, " r" );
80+ if (program != NULL ) {
81+ Local<Array> argStack = Local<Array>::New (Array::New (frames));
82+ for (int i = 0 ; i < frames; i++) {
83+ if (fgets (buffer, sizeof (buffer), program) == NULL ) {
84+ buffer[0 ] = ' \0 ' ;
85+ }
86+ int len = strlen (buffer);
87+ if (len > 0 && buffer[len - 1 ] == ' \n ' ) {
88+ buffer[len - 1 ] = ' \0 ' ;
89+ }
90+ argStack->Set (i, String::New (buffer));
91+ }
92+ pclose (program);
93+
94+ Local<Value> argv[3 ] = {argStack, Local<Value>::New (Number::New (si->si_signo )), Local<Value>::New (Number::New ((unsigned long long )si->si_addr ))};
95+ callback->Call (Context::GetCurrent ()->Global (), 3 , argv);
96+ }
97+ else {
98+ emptyCallback (si);
99+ }
100+ }
101+ else {
102+ emptyCallback (si);
103+ }
104+ #else
105+ emptyCallback (si);
106+ #endif
44107 }
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);
48108 }
49109
50110 // Re-send the signal, this time a default handler will be called
@@ -101,7 +161,7 @@ Handle<Value> RegisterHandler(const Arguments& args) {
101161 struct sigaction sa;
102162 memset (&sa, 0 , sizeof (struct sigaction ));
103163 sigemptyset (&sa.sa_mask );
104- sa.sa_sigaction = segfault_handler ;
164+ sa.sa_sigaction = segfaultHandler ;
105165 sa.sa_flags = SA_SIGINFO | SA_RESETHAND; // We set SA_RESETHAND so that our handler is called only once
106166 sigaction (SIGSEGV, &sa, NULL );
107167 sigaction (SIGBUS, &sa, NULL );
0 commit comments