From 1dda0a4212d4125ab04d4c1cf8d150f27b6c4afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com> Date: Wed, 4 Apr 2018 23:23:00 +0200 Subject: [PATCH] Clean-up of backtrace handler --- utils/BacktraceManager.cpp | 62 ++++++++++++++++++++++++ utils/BacktraceManager.hpp | 21 +++++++++ utils/CMakeLists.txt | 1 + utils/SignalManager.cpp | 97 ++++++++------------------------------ utils/SignalManager.hpp | 4 +- 5 files changed, 105 insertions(+), 80 deletions(-) create mode 100644 utils/BacktraceManager.cpp create mode 100644 utils/BacktraceManager.hpp diff --git a/utils/BacktraceManager.cpp b/utils/BacktraceManager.cpp new file mode 100644 index 000000000..8df01921e --- /dev/null +++ b/utils/BacktraceManager.cpp @@ -0,0 +1,62 @@ +#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; +} diff --git a/utils/BacktraceManager.hpp b/utils/BacktraceManager.hpp new file mode 100644 index 000000000..cb2fdc9f9 --- /dev/null +++ b/utils/BacktraceManager.hpp @@ -0,0 +1,21 @@ +#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 diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index b1a57d9cf..e8877d862 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -5,6 +5,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_library( PastisUtils + BacktraceManager.cpp ConsoleManager.cpp FPEManager.cpp RevisionInfo.cpp diff --git a/utils/SignalManager.cpp b/utils/SignalManager.cpp index ab84325bb..271720d0d 100644 --- a/utils/SignalManager.cpp +++ b/utils/SignalManager.cpp @@ -1,79 +1,20 @@ #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); } } diff --git a/utils/SignalManager.hpp b/utils/SignalManager.hpp index d4ff3239d..6232fdee2 100644 --- a/utils/SignalManager.hpp +++ b/utils/SignalManager.hpp @@ -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); -- GitLab