00001
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef __GNUC__
00037 # error unknown compiler (not gcc/g++), no glibc backtracing
00038 #endif
00039
00040
00041 #ifdef __cplusplus
00042 extern "C" {
00043
00044 # define DEMANGLE
00045 # include <cxxabi.h>
00046 #endif
00047
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <unistd.h>
00051 #include <signal.h>
00052 #include <string.h>
00053 #include <errno.h>
00054 #include <execinfo.h>
00055 #include <sys/resource.h>
00056 #include "sense_impl.h"
00057 #include "stacktrace.h"
00058 #define TRACELEN 50
00059
00060
00061 unsigned printStackTrace(const char *exception, const char *file,
00062 unsigned int line) {
00063 void *addrs[TRACELEN];
00064 size_t i, depth = backtrace(addrs, TRACELEN);
00065 char **strings = backtrace_symbols(addrs, depth);
00066
00067 if (strings == NULL)
00068 return 0;
00069 log_error("%s: %sException in %s, line %d:\n", APP, exception, file, line);
00070
00071 for (i = 0; i < depth; i++) {
00072 #if 0 //DEMANGLE
00073 size_t max_name = 1024;
00074 char *begin = 0, *end = 0;
00075 char *name = static_cast<char*>(malloc(max_name));
00076 if (name == NULL)
00077 return 0;
00078
00079 for (char *j = strings[i]; *j; ++j) {
00080 if (*j == '(')
00081 begin = j;
00082 else if (*j == '+')
00083 end = j;
00084 }
00085 if (begin && end) {
00086 *begin++ = '\0';
00087 *end = '\0';
00088
00089 int ignore;
00090 char *ret = abi::__cxa_demangle(begin, name, &max_name, &ignore);
00091 if (ret)
00092 name = ret;
00093 else {
00094 strncpy(name, begin, max_name);
00095 strncat(name, "()", max_name);
00096 name[max_name - 1] = '\0';
00097 }
00098 log_error("%s: %s(%s)\n", APP, strings[i], name);
00099 }
00100 else
00101 log_error("%s: %s\n", APP, strings[i]);
00102 free(name);
00103 #else // ! DEMANGLE
00104 log_error("%s: %s\n", APP, strings[i]);
00105 #endif
00106 }
00107 free(strings);
00108 return 1;
00109 }
00110
00111
00112 static void segv_handler(int sig, siginfo_t* info, void* ptr)
00113 {
00114
00115 void *addrs[TRACELEN];
00116 size_t depth = backtrace(addrs, TRACELEN);
00117
00118 fprintf(stderr, "*** SEGFAULT (sig %d) - ", sig);
00119 fprintf(stderr, "%d stack frames ***\n", depth);
00120
00121 backtrace_symbols_fd(addrs, depth, STDERR_FILENO);
00122 exit(-1);
00123 }
00124
00125
00126 int enable_backtrace()
00127 {
00128 struct sigaction action;
00129 struct rlimit limit;
00130
00131 memset(&action, 0, sizeof(action));
00132 action.sa_sigaction = segv_handler;
00133 action.sa_flags = SA_SIGINFO;
00134 if(sigaction(SIGSEGV, &action, NULL) < 0) {
00135 log_error("Failed to install SEGV backtrace facility (sigaction %s).\n",
00136 strerror(errno));
00137 return -1;
00138 }
00139
00140 memset(&limit, 0, sizeof(limit));
00141 limit.rlim_cur = RLIM_INFINITY;
00142 limit.rlim_max = RLIM_INFINITY;
00143 setrlimit(RLIMIT_CORE, &limit);
00144 return 0;
00145 }
00146
00147 static void __attribute((constructor)) init(void) {
00148 enable_backtrace();
00149 }
00150
00151 # ifdef __cplusplus
00152 }
00153 # endif