Wittyshare  0.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
WsCrashLogger.cpp
Go to the documentation of this file.
1 /*
2  * =====================================================================================
3  *
4  * Filename: WsCrashLogger.cpp
5  *
6  * Description: Logs WS crashes
7  *
8  * Version: 1.0
9  * Created: 27/11/13 09:57:10
10  * Revision: none
11  * Compiler: g++
12  *
13  * Author: Benoit Daccache, ben.daccache@gmail.com
14  *
15  * =====================================================================================
16  */
17 
18 #include "WsCrashLogger.h"
19 
20 #include <Include/WsGlobalConfig.h>
21 #include <unistd.h>
22 #include <iostream>
23 #include <stdlib.h>
24 #include <signal.h>
25 #include <execinfo.h>
26 #include <cxxabi.h>
27 
28 void WsCrashLogger::printStackTrace(FILE* out, unsigned int maxFrames)
29 {
30  fprintf(out, "Stack trace:\n");
31  // storage array for stack trace address data
32  void* addrlist[maxFrames + 1];
33  // retrieve current stack addresses
34  unsigned int addrlen = backtrace( addrlist, sizeof( addrlist ) / sizeof( void* ));
35  if ( addrlen == 0 ) {
36  fprintf( out, " \n" );
37  return;
38  }
39  // resolve addresses into strings containing "filename(function+address)",
40  // Actually it will be ## program address function + offset
41  // this array must be free()-ed
42  char** symbollist = backtrace_symbols( addrlist, addrlen );
43  size_t funcnamesize = 1024;
44  char funcname[1024];
45  // iterate over the returned symbol lines. skip the first, it is the
46  // address of this function.
47  for ( unsigned int i = 4; i < addrlen; i++ ) {
48  char* begin_name = NULL;
49  char* begin_offset = NULL;
50  char* end_offset = NULL;
51  // find parentheses and +address offset surrounding the mangled name
52  for ( char* p = symbollist[i]; *p; ++p ) {
53  if ( *p == '(' )
54  begin_name = p;
55  else if ( *p == '+' )
56  begin_offset = p;
57  else if ( *p == ')' && ( begin_offset || begin_name ))
58  end_offset = p;
59  }
60  if ( begin_name && end_offset && ( begin_name < end_offset )) {
61  *begin_name++ = '\0';
62  *end_offset++ = '\0';
63  if ( begin_offset )
64  *begin_offset++ = '\0';
65  // mangled name is now in [begin_name, begin_offset) and caller
66  // offset in [begin_offset, end_offset). now apply
67  // __cxa_demangle():
68  int status = 0;
69  char* ret = abi::__cxa_demangle( begin_name, funcname,
70  &funcnamesize, &status );
71  char* fname = begin_name;
72  if ( status == 0 )
73  fname = ret;
74  if ( begin_offset ) {
75  fprintf( out, " %-30s ( %-40s + %-6s) %s\n",
76  symbollist[i], fname, begin_offset, end_offset );
77  } else {
78  fprintf( out, " %-30s ( %-40s %-6s) %s\n",
79  symbollist[i], fname, "", end_offset );
80  }
81  } else {
82  // couldn't parse the line? print the whole line.
83  fprintf(out, " %-40s\n", symbollist[i]);
84  }
85  }
86  free(symbollist);
87 }
89 {
90  const char* name = NULL;
91  switch ( signum ) {
92  case SIGABRT:
93  name = "SIGABRT";
94  break;
95  case SIGSEGV:
96  name = "SIGSEGV";
97  break;
98  case SIGILL:
99  name = "SIGILL";
100  break;
101  case SIGFPE:
102  name = "SIGFPE";
103  break;
104  }
105  if ( name )
106  fprintf( stderr, "Caught signal %d (%s)\n", signum, name );
107  else
108  fprintf( stderr, "Caught signal %d\n", signum );
109  // Dump a stack trace.
110  FILE* f = fopen(GlobalConfig::CrashLogPath.c_str(), "w");
111  printStackTrace(f, 62);
112  fclose(f);
113  exit( signum );
114 }
115 
const std::string CrashLogPath
static void handleSignal(int signum)
static void printStackTrace(FILE *out=stderr, unsigned int maxFrames=63)