2015-09-29 22:43:55 +02:00
|
|
|
#include "backtrace.h"
|
|
|
|
#include <execinfo.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <unistd.h>
|
2015-10-05 14:58:16 +02:00
|
|
|
#include <cxxabi.h>
|
|
|
|
#include <string>
|
2015-10-05 15:46:50 +02:00
|
|
|
#include <sstream>
|
2015-10-17 03:08:56 +02:00
|
|
|
#include "../logging/logging.h"
|
2015-10-05 14:58:16 +02:00
|
|
|
|
|
|
|
using std::string;
|
2015-10-05 15:46:50 +02:00
|
|
|
using std::ostringstream;
|
2015-10-17 03:08:56 +02:00
|
|
|
using namespace cpputils::logging;
|
2015-09-29 22:43:55 +02:00
|
|
|
|
2015-09-29 22:52:06 +02:00
|
|
|
//TODO Use the following? https://github.com/bombela/backward-cpp
|
|
|
|
|
2015-09-29 22:43:55 +02:00
|
|
|
namespace cpputils {
|
|
|
|
|
2015-10-05 15:46:50 +02:00
|
|
|
//TODO Refactor (for example: RAII or at least try{}finally{} instead of free())
|
2015-10-05 14:58:16 +02:00
|
|
|
|
|
|
|
std::string demangle(const string &mangledName) {
|
|
|
|
string result;
|
|
|
|
int status = -10;
|
|
|
|
char *demangledName = abi::__cxa_demangle(mangledName.c_str(), NULL, NULL, &status);
|
|
|
|
if (status == 0) {
|
|
|
|
result = demangledName;
|
|
|
|
} else {
|
|
|
|
result = mangledName;
|
|
|
|
}
|
|
|
|
free(demangledName);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string pretty(const string &backtraceLine) {
|
|
|
|
size_t startMangledName = backtraceLine.find('(');
|
|
|
|
size_t endMangledName = backtraceLine.find('+');
|
|
|
|
if (startMangledName == string::npos || endMangledName == string::npos) {
|
|
|
|
return backtraceLine;
|
|
|
|
}
|
|
|
|
return demangle(backtraceLine.substr(startMangledName+1, endMangledName-startMangledName-1)) + ": (" + backtraceLine.substr(0, startMangledName) + backtraceLine.substr(endMangledName);
|
|
|
|
}
|
|
|
|
|
2015-10-05 15:46:50 +02:00
|
|
|
string backtrace_to_string(void *array[], size_t size) {
|
|
|
|
ostringstream result;
|
2015-10-05 14:58:16 +02:00
|
|
|
char **ptr = backtrace_symbols(array, size);
|
|
|
|
for (size_t i = 0; i < size; ++i) {
|
2015-10-05 15:46:50 +02:00
|
|
|
result << pretty(ptr[i]) << "\n";
|
2015-10-05 14:58:16 +02:00
|
|
|
}
|
|
|
|
free(ptr);
|
2015-10-05 15:46:50 +02:00
|
|
|
return result.str();
|
2015-10-05 14:58:16 +02:00
|
|
|
}
|
|
|
|
|
2015-10-05 15:46:50 +02:00
|
|
|
string backtrace() {
|
2015-10-03 01:23:30 +02:00
|
|
|
constexpr unsigned int MAX_SIZE = 100;
|
|
|
|
void *array[MAX_SIZE];
|
2015-10-05 15:46:50 +02:00
|
|
|
size_t size = ::backtrace(array, MAX_SIZE);
|
|
|
|
return backtrace_to_string(array, size);
|
|
|
|
}
|
2015-09-29 22:43:55 +02:00
|
|
|
|
2015-10-05 15:46:50 +02:00
|
|
|
void sigsegv_handler(int) {
|
2015-10-17 03:08:56 +02:00
|
|
|
LOG(ERROR) << "SIGSEGV\n" << backtrace();
|
2015-09-29 22:43:55 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void showBacktraceOnSigSegv() {
|
|
|
|
signal(SIGSEGV, sigsegv_handler);
|
|
|
|
}
|
|
|
|
}
|