Skip to content
Snippets Groups Projects
Commit 1dda0a42 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Clean-up of backtrace handler

parent aa2ee664
Branches
Tags
No related merge requests found
#include <BacktraceManager.hpp>
#include <iomanip>
#include <rang.hpp>
#include <execinfo.h>
#include <cxxabi.h>
#include <regex>
#include <cmath>
BacktraceManager::
BacktraceManager()
{
const int size = 100;
void *buffer[size];
int ret = ::backtrace(buffer, size);
char **ptr = backtrace_symbols(buffer, ret);
for (int i=2; i<ret; ++i) {
m_lines.push_back(ptr[i]);
}
free(ptr);
}
std::ostream& operator<<(std::ostream& os,
const BacktraceManager& btm)
{
const std::vector<std::string>& lines = btm.m_lines;
const std::regex mangled_function(R"%(\(.*\+)%");
const int width=std::log10(lines.size())+1;
for (size_t i_line=0; i_line<lines.size(); ++i_line) {
const auto& line = lines[i_line];
os << rang::fg::green << "[" << std::setw(width) << i_line+1 << '/' << lines.size() << "] " << rang::fg::reset;
std::smatch matchex;
int status = -1;
if (std::regex_search(line, matchex, mangled_function)) {
std::string prefix = matchex.prefix().str();
std::string function = line.substr(matchex.position()+1,matchex.length()-2);
std::string suffix = matchex.suffix().str();
os << prefix << '(';
if (function.size() > 0) {
char* demangled = abi::__cxa_demangle(function.c_str(), NULL, NULL, &status);
if (status==0) {
os << rang::fgB::yellow << demangled << rang::fg::reset;
free(demangled);
} else {
os << rang::fgB::yellow << function << rang::fg::reset;
}
}
os<< '+' << suffix << '\n';
} else {
os << line << '\n';
}
}
return os;
}
#ifndef BACKTRACE_MANAGER_HPP
#define BACKTRACE_MANAGER_HPP
#include <vector>
#include <string>
class BacktraceManager
{
private:
std::vector<std::string> m_lines;
public:
BacktraceManager();
friend std::ostream& operator<<(std::ostream& os, const BacktraceManager& btm);
BacktraceManager(const BacktraceManager&) = default;
~BacktraceManager() = default;
};
#endif // BACKTRACE_MANAGER_HPP
......@@ -5,6 +5,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_library(
PastisUtils
BacktraceManager.cpp
ConsoleManager.cpp
FPEManager.cpp
RevisionInfo.cpp
......
#include <SignalManager.hpp>
#include <BacktraceManager.hpp>
#include <ConsoleManager.hpp>
#include <Kokkos_Core.hpp>
#include <csignal>
#include <rang.hpp>
#include <iomanip>
#include <execinfo.h>
#include <cxxabi.h>
#include <regex>
#include <vector>
std::vector<std::string> getBacktrace()
{
const int size = 100;
void *buffer[size];
int ret = ::backtrace(buffer, size);
char **ptr = backtrace_symbols( buffer, ret );
std::vector<std::string> backtrace;
for (int i=2; i<ret; ++i) {
backtrace.push_back(ptr[i]);
}
free(ptr);
return backtrace;
}
void print_bt() {
const std::vector<std::string> lines = getBacktrace();
const std::regex mangled_function(R"%(\(.*\+)%");
const int width=std::log10(lines.size())+1;
for (size_t i_line=0; i_line<lines.size(); ++i_line) {
const auto& line = lines[i_line];
std::cerr << rang::fg::green << "[" << std::setw(width) << i_line+1 << '/' << lines.size() << "] " << rang::fg::reset;
std::smatch matchex;
int status = -1;
if (std::regex_search(line, matchex, mangled_function)) {
std::string prefix = matchex.prefix().str();
std::string function = line.substr(matchex.position()+1,matchex.length()-2);
std::string suffix = matchex.suffix().str();
std::cerr << prefix << '(';
if (function.size() > 0) {
char* demangled = abi::__cxa_demangle(function.c_str(), NULL, NULL, &status);
if (status==0) {
std::cerr << rang::fgB::yellow << demangled << rang::fg::reset;
free(demangled);
} else {
std::cerr << rang::fgB::yellow << function << rang::fg::reset;
}
}
std::cerr<< '+' << suffix << '\n';
} else {
std::cerr << line << '\n';
}
}
}
#warning must create a specific class for pausing and use enum class
#include <string>
std::string SignalManager::s_pause_on_error = "auto";
void SignalManager::setPauseForDebug(const std::string& pause_on_error)
{
s_pause_on_error = pause_on_error;
}
std::string SignalManager::signalName(int s)
std::string SignalManager::signalName(const int& signal)
{
switch (s) {
switch (signal) {
case SIGILL: return "SIGILL";
case SIGFPE: return "SIGFPE";
case SIGABRT: return "SIGABRT";
......@@ -84,33 +25,32 @@ std::string SignalManager::signalName(int s)
return "SIGNAL undefined!";
}
void SignalManager::pauseForDebug()
void SignalManager::pauseForDebug(const int& signal)
{
std::cout << "\n======================================" << std::endl;
std::cout << "\n======================================\n";
std::cout << rang::style::reset
<< rang::fg::reset
<< rang::style::bold;
std::cout << "to attach gdb to this process run" << std::endl;
std::cout << "to attach gdb to this process run\n";
std::cout << "\tgdb -pid "
<< rang::fg::red
<< getpid()
<< rang::fg::reset
<< '\n';
std::cout << "else press Control-C to exit" << std::endl;
std::cout << "else press Control-C to exit\n";
std::cout << rang::style::reset;
std::cout << "======================================" << std::endl;
std::cout << "======================================\n";
std::cout << std::flush;
::sigset_t sig;
::sigaddset(&sig,SIGSTOP);
::sigsuspend(&sig);
std::exit(1);
std::exit(signal);
}
void SignalManager::handler(int s)
void SignalManager::handler(int signal)
{
std::signal(SIGFPE, SIG_DFL);
std::signal(SIGSEGV, SIG_IGN);
......@@ -118,26 +58,27 @@ void SignalManager::handler(int s)
std::signal(SIGINT, SIG_DFL);
std::signal(SIGABRT, SIG_DFL);
std::cout << "\n *** "
std::cerr << "\n *** "
<< rang::style::reset
<< rang::fg::reset
<< rang::style::bold;
std::cout << "Signal "
std::cerr << "Signal "
<< rang::fgB::yellow
<< signalName(s)
<< signalName(signal)
<< rang::fg::reset
<< " caught"
<< rang::style::reset
<< " ***\n";
print_bt();
BacktraceManager bm;
std::cerr << bm << '\n';
if ((ConsoleManager::isTerminal(std::cout) and
(s_pause_on_error == "auto")) or
(s_pause_on_error == "yes")) {
SignalManager::pauseForDebug();
SignalManager::pauseForDebug(signal);
} else {
std::exit(1);
std::exit(signal);
}
}
......
......@@ -7,8 +7,8 @@ struct SignalManager
{
private:
static std::string s_pause_on_error;
static std::string signalName(int signal);
static void pauseForDebug();
static std::string signalName(const int& signal);
static void pauseForDebug(const int& signal);
static void handler(int signal);
public:
static void setPauseForDebug(const std::string& pause_on_error);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment