Add line numbers to stack trace

This commit is contained in:
Jason Bosco 2021-01-22 16:48:10 -08:00
parent ef1306befe
commit 52287b263d
3 changed files with 91 additions and 23 deletions

View File

@ -3,8 +3,8 @@ project(typesense)
cmake_policy(SET CMP0074 NEW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wno-unused-parameter -O2")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wno-unused-parameter -std=c++11 -O0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wno-unused-parameter -O2 -g")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Wextra -Wno-unused-parameter -std=c++11 -O0 -g")
set(DEP_ROOT_DIR ${CMAKE_SOURCE_DIR}/external-${CMAKE_SYSTEM_NAME})
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

83
include/stackprinter.h Normal file
View File

@ -0,0 +1,83 @@
#include <string>
#include <unistd.h>
#include <execinfo.h>
#include <regex>
class StackPrinter {
public:
static std::string getexepath() {
char result[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
return std::string(result, (count > 0) ? count : 0);
}
static std::string sh(const std::string& cmd) {
std::array<char, 128> buffer;
std::string result;
std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
if (!pipe) throw std::runtime_error("popen() failed!");
size_t bt_num = 0;
std::string optional_space;
#if __linux__
optional_space = " ";
#endif
while (!feof(pipe.get())) {
if (fgets(buffer.data(), 128, pipe.get()) != nullptr) {
if(bt_num++ % 2 == 1) {
result += optional_space + buffer.data();
} else {
result += buffer.data();
}
}
}
return result;
}
static void bt_sighandler(int sig) {
LOG(ERROR) << "Typesense crashed. Generating stack trace...";
void *bt[1024];
int bt_size;
char **bt_syms;
int i;
bt_size = backtrace(bt, 1024);
bt_syms = backtrace_symbols(bt, bt_size);
std::regex linux_address_re("\\[(.+)\\]");
std::string addrs;
for (i = 1; i < bt_size; i++) {
std::string sym = bt_syms[i];
#if __linux__
std::smatch matches;
if (std::regex_search(sym, matches, linux_address_re)) {
std::string addr = matches[1];
addrs += " " + addr;
}
#elif __APPLE__
std::vector<std::string> sym_parts;
StringUtils::split(sym, sym_parts, " ");
addrs += " " + (sym_parts.size() > 2 ? sym_parts[2] : "");
#else
LOG(ERROR) << sym;
#endif
}
#if __linux__
std::string command = std::string("addr2line -e ") + getexepath() + " -f -C " + addrs;
LOG(ERROR) << sh(command);
#elif __APPLE__
std::string command = std::string("atos -p ") + std::to_string(getpid()) + " " + addrs;
LOG(ERROR) << sh(command);
#endif
free(bt_syms);
exit(1);
}
};

View File

@ -19,6 +19,8 @@
#include "threadpool.h"
#include "jemalloc.h"
#include "stackprinter.h"
HttpServer* server;
std::atomic<bool> quit_raft_service;
@ -43,22 +45,6 @@ void catch_interrupt(int sig) {
quit_raft_service = true;
}
void catch_crash(int sig) {
void *bt[1024];
char **bt_syms;
size_t bt_size;
bt_size = backtrace(bt, 1024);
bt_syms = backtrace_symbols(bt, bt_size);
LOG(ERROR) << "Typesense crashed...";
for (size_t i = 0; i < bt_size; i++) {
LOG(ERROR) << bt_syms[i];
}
exit(-1);
}
Option<std::string> fetch_file_contents(const std::string & file_path) {
if(!file_exists(file_path)) {
return Option<std::string>(404, std::string("File does not exist at: ") + file_path);
@ -106,11 +92,10 @@ void init_cmdline_options(cmdline::parser & options, int argc, char **argv) {
}
int init_logger(Config & config, const std::string & server_version) {
// remove SIGTERM since we handle it on our own
signal(SIGABRT, catch_crash);
signal(SIGFPE, catch_crash);
signal(SIGILL, catch_crash);
signal(SIGSEGV, catch_crash);
signal(SIGABRT, StackPrinter::bt_sighandler);
signal(SIGFPE, StackPrinter::bt_sighandler);
signal(SIGILL, StackPrinter::bt_sighandler);
signal(SIGSEGV, StackPrinter::bt_sighandler);
// we can install new signal handlers only after overriding above
signal(SIGINT, catch_interrupt);