mirror of https://github.com/Icinga/icinga2.git
Replace icinga::StackTrace with boost::stacktrace::stacktrace
Provides roughly the same functionality but works better on certain platforms (especially Windows) and is less code to maintain.
This commit is contained in:
parent
e11b4b7b55
commit
5cb7c7cc09
|
@ -64,7 +64,6 @@ set(base_SOURCES
|
|||
shared-object.hpp
|
||||
singleton.hpp
|
||||
socket.cpp socket.hpp
|
||||
stacktrace.cpp stacktrace.hpp
|
||||
statsfunction.hpp
|
||||
stdiostream.cpp stdiostream.hpp
|
||||
stream.cpp stream.hpp
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "base/application.hpp"
|
||||
#include "base/application-ti.cpp"
|
||||
#include "base/stacktrace.hpp"
|
||||
#include "base/timer.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/exception.hpp"
|
||||
|
@ -761,9 +760,7 @@ void Application::SigAbrtHandler(int)
|
|||
|
||||
DisplayInfoMessage(ofs);
|
||||
|
||||
StackTrace trace;
|
||||
ofs << "Stacktrace:" << "\n";
|
||||
trace.Print(ofs, 1);
|
||||
ofs << "\nStacktrace:\n" << boost::stacktrace::stacktrace() << "\n";
|
||||
|
||||
DisplayBugMessage(ofs);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
using namespace icinga;
|
||||
|
||||
static boost::thread_specific_ptr<StackTrace> l_LastExceptionStack;
|
||||
static boost::thread_specific_ptr<boost::stacktrace::stacktrace> l_LastExceptionStack;
|
||||
static boost::thread_specific_ptr<ContextTrace> l_LastExceptionContext;
|
||||
|
||||
#ifdef HAVE_CXXABI_H
|
||||
|
@ -113,7 +113,7 @@ void __cxa_throw(void *obj, TYPEINFO_TYPE *pvtinfo, void (*dest)(void *))
|
|||
|
||||
if (!uex) {
|
||||
#endif /* NO_CAST_EXCEPTION */
|
||||
StackTrace stack;
|
||||
boost::stacktrace::stacktrace stack;
|
||||
SetLastExceptionStack(stack);
|
||||
|
||||
#ifndef NO_CAST_EXCEPTION
|
||||
|
@ -134,14 +134,14 @@ void __cxa_throw(void *obj, TYPEINFO_TYPE *pvtinfo, void (*dest)(void *))
|
|||
}
|
||||
#endif /* HAVE_CXXABI_H */
|
||||
|
||||
StackTrace *icinga::GetLastExceptionStack()
|
||||
boost::stacktrace::stacktrace *icinga::GetLastExceptionStack()
|
||||
{
|
||||
return l_LastExceptionStack.get();
|
||||
}
|
||||
|
||||
void icinga::SetLastExceptionStack(const StackTrace& trace)
|
||||
void icinga::SetLastExceptionStack(const boost::stacktrace::stacktrace& trace)
|
||||
{
|
||||
l_LastExceptionStack.reset(new StackTrace(trace));
|
||||
l_LastExceptionStack.reset(new boost::stacktrace::stacktrace(trace));
|
||||
}
|
||||
|
||||
ContextTrace *icinga::GetLastExceptionContext()
|
||||
|
@ -154,7 +154,7 @@ void icinga::SetLastExceptionContext(const ContextTrace& context)
|
|||
l_LastExceptionContext.reset(new ContextTrace(context));
|
||||
}
|
||||
|
||||
String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, StackTrace *stack, ContextTrace *context)
|
||||
String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, boost::stacktrace::stacktrace *stack, ContextTrace *context)
|
||||
{
|
||||
std::ostringstream result;
|
||||
|
||||
|
@ -216,7 +216,7 @@ String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, Sta
|
|||
const auto *pex = dynamic_cast<const posix_error *>(&ex);
|
||||
|
||||
if (!uex && !pex && verbose) {
|
||||
const StackTrace *st = boost::get_error_info<StackTraceErrorInfo>(ex);
|
||||
const boost::stacktrace::stacktrace *st = boost::get_error_info<StackTraceErrorInfo>(ex);
|
||||
|
||||
if (st) {
|
||||
result << *st;
|
||||
|
@ -251,8 +251,8 @@ String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, Sta
|
|||
|
||||
String icinga::DiagnosticInformation(const boost::exception_ptr& eptr, bool verbose)
|
||||
{
|
||||
StackTrace *pt = GetLastExceptionStack();
|
||||
StackTrace stack;
|
||||
boost::stacktrace::stacktrace *pt = GetLastExceptionStack();
|
||||
boost::stacktrace::stacktrace stack;
|
||||
|
||||
ContextTrace *pc = GetLastExceptionContext();
|
||||
ContextTrace context;
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include "base/i2-base.hpp"
|
||||
#include "base/string.hpp"
|
||||
#include "base/stacktrace.hpp"
|
||||
#include "base/context.hpp"
|
||||
#include "base/debuginfo.hpp"
|
||||
#include "base/dictionary.hpp"
|
||||
|
@ -15,6 +14,7 @@
|
|||
#include <boost/exception/errinfo_file_name.hpp>
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <boost/stacktrace.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <boost/algorithm/string/trim.hpp>
|
||||
|
@ -76,15 +76,16 @@ private:
|
|||
Dictionary::Ptr m_DebugHint;
|
||||
};
|
||||
|
||||
StackTrace *GetLastExceptionStack();
|
||||
void SetLastExceptionStack(const StackTrace& trace);
|
||||
boost::stacktrace::stacktrace *GetLastExceptionStack();
|
||||
void SetLastExceptionStack(const boost::stacktrace::stacktrace& trace);
|
||||
|
||||
ContextTrace *GetLastExceptionContext();
|
||||
void SetLastExceptionContext(const ContextTrace& context);
|
||||
|
||||
void RethrowUncaughtException();
|
||||
|
||||
typedef boost::error_info<StackTrace, StackTrace> StackTraceErrorInfo;
|
||||
struct errinfo_stacktrace_;
|
||||
typedef boost::error_info<struct errinfo_stacktrace_, boost::stacktrace::stacktrace> StackTraceErrorInfo;
|
||||
|
||||
std::string to_string(const StackTraceErrorInfo&);
|
||||
|
||||
|
@ -92,7 +93,8 @@ typedef boost::error_info<ContextTrace, ContextTrace> ContextTraceErrorInfo;
|
|||
|
||||
std::string to_string(const ContextTraceErrorInfo& e);
|
||||
|
||||
String DiagnosticInformation(const std::exception& ex, bool verbose = true, StackTrace *stack = nullptr, ContextTrace *context = nullptr);
|
||||
String DiagnosticInformation(const std::exception& ex, bool verbose = true,
|
||||
boost::stacktrace::stacktrace *stack = nullptr, ContextTrace *context = nullptr);
|
||||
String DiagnosticInformation(const boost::exception_ptr& eptr, bool verbose = true);
|
||||
|
||||
class posix_error : virtual public std::exception, virtual public boost::exception {
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#include "base/stacktrace.hpp"
|
||||
#include "base/utility.hpp"
|
||||
#include "base/initialize.hpp"
|
||||
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
# include <execinfo.h>
|
||||
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma optimize("", off)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
StackTrace::StackTrace()
|
||||
{
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
m_Count = backtrace(m_Frames, sizeof(m_Frames) / sizeof(m_Frames[0]));
|
||||
#else /* HAVE_BACKTRACE_SYMBOLS */
|
||||
# ifdef _WIN32
|
||||
m_Count = CaptureStackBackTrace(0, sizeof(m_Frames) / sizeof(m_Frames), m_Frames, nullptr);
|
||||
# else /* _WIN32 */
|
||||
m_Count = 0;
|
||||
# endif /* _WIN32 */
|
||||
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma optimize("", on)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#ifdef _WIN32
|
||||
StackTrace::StackTrace(PEXCEPTION_POINTERS exi)
|
||||
{
|
||||
STACKFRAME64 frame;
|
||||
int architecture;
|
||||
|
||||
#ifdef _WIN64
|
||||
architecture = IMAGE_FILE_MACHINE_AMD64;
|
||||
|
||||
frame.AddrPC.Offset = exi->ContextRecord->Rip;
|
||||
frame.AddrFrame.Offset = exi->ContextRecord->Rbp;
|
||||
frame.AddrStack.Offset = exi->ContextRecord->Rsp;
|
||||
#else /* _WIN64 */
|
||||
architecture = IMAGE_FILE_MACHINE_I386;
|
||||
|
||||
frame.AddrPC.Offset = exi->ContextRecord->Eip;
|
||||
frame.AddrFrame.Offset = exi->ContextRecord->Ebp;
|
||||
frame.AddrStack.Offset = exi->ContextRecord->Esp;
|
||||
#endif /* _WIN64 */
|
||||
|
||||
frame.AddrPC.Mode = AddrModeFlat;
|
||||
frame.AddrFrame.Mode = AddrModeFlat;
|
||||
frame.AddrStack.Mode = AddrModeFlat;
|
||||
|
||||
m_Count = 0;
|
||||
|
||||
while (StackWalk64(architecture, GetCurrentProcess(), GetCurrentThread(),
|
||||
&frame, exi->ContextRecord, nullptr, &SymFunctionTableAccess64,
|
||||
&SymGetModuleBase64, nullptr) && m_Count < sizeof(m_Frames) / sizeof(m_Frames[0])) {
|
||||
m_Frames[m_Count] = reinterpret_cast<void *>(frame.AddrPC.Offset);
|
||||
m_Count++;
|
||||
}
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifdef _WIN32
|
||||
INITIALIZE_ONCE([]() {
|
||||
(void) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
|
||||
(void) SymInitialize(GetCurrentProcess(), nullptr, TRUE);
|
||||
});
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/**
|
||||
* Prints a stacktrace to the specified stream.
|
||||
*
|
||||
* @param fp The stream.
|
||||
* @param ignoreFrames The number of stackframes to ignore (in addition to
|
||||
* the one this function is executing in).
|
||||
* @returns true if the stacktrace was printed, false otherwise.
|
||||
*/
|
||||
void StackTrace::Print(std::ostream& fp, int ignoreFrames) const
|
||||
{
|
||||
fp << std::endl;
|
||||
|
||||
#ifndef _WIN32
|
||||
# ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
char **messages = backtrace_symbols(m_Frames, m_Count);
|
||||
|
||||
for (int i = ignoreFrames + 1; i < m_Count && messages; ++i) {
|
||||
String message = messages[i];
|
||||
|
||||
char *sym_begin = strchr(messages[i], '(');
|
||||
|
||||
if (sym_begin) {
|
||||
char *sym_end = strchr(sym_begin, '+');
|
||||
|
||||
if (sym_end) {
|
||||
String sym = String(sym_begin + 1, sym_end);
|
||||
String sym_demangled = Utility::DemangleSymbolName(sym);
|
||||
|
||||
if (sym_demangled.IsEmpty())
|
||||
sym_demangled = "<unknown function>";
|
||||
|
||||
String path = String(messages[i], sym_begin);
|
||||
|
||||
size_t slashp = path.RFind("/");
|
||||
|
||||
if (slashp != String::NPos)
|
||||
path = path.SubStr(slashp + 1);
|
||||
|
||||
message = path + ": " + sym_demangled + " (" + String(sym_end);
|
||||
}
|
||||
}
|
||||
|
||||
fp << "\t(" << i - ignoreFrames - 1 << ") " << message << std::endl;
|
||||
}
|
||||
|
||||
std::free(messages);
|
||||
|
||||
fp << std::endl;
|
||||
# else /* HAVE_BACKTRACE_SYMBOLS */
|
||||
fp << "(not available)" << std::endl;
|
||||
# endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||
#else /* _WIN32 */
|
||||
for (int i = ignoreFrames + 1; i < m_Count; i++) {
|
||||
fp << "\t(" << i - ignoreFrames - 1 << "): " << Utility::GetSymbolName(m_Frames[i]) << std::endl;
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
std::ostream& icinga::operator<<(std::ostream& stream, const StackTrace& trace)
|
||||
{
|
||||
trace.Print(stream, 1);
|
||||
|
||||
return stream;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#ifndef STACKTRACE_H
|
||||
#define STACKTRACE_H
|
||||
|
||||
#include "base/i2-base.hpp"
|
||||
#include <iosfwd>
|
||||
|
||||
namespace icinga
|
||||
{
|
||||
|
||||
/**
|
||||
* A stacktrace.
|
||||
*
|
||||
* @ingroup base
|
||||
*/
|
||||
class StackTrace
|
||||
{
|
||||
public:
|
||||
StackTrace();
|
||||
#ifdef _WIN32
|
||||
explicit StackTrace(PEXCEPTION_POINTERS exi);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
void Print(std::ostream& fp, int ignoreFrames = 0) const;
|
||||
|
||||
static void StaticInitialize();
|
||||
|
||||
private:
|
||||
void *m_Frames[64];
|
||||
int m_Count;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const StackTrace& trace);
|
||||
|
||||
}
|
||||
|
||||
#endif /* UTILITY_H */
|
|
@ -16,7 +16,6 @@ set(base_test_SOURCES
|
|||
base-object-packer.cpp
|
||||
base-serialize.cpp
|
||||
base-shellescape.cpp
|
||||
base-stacktrace.cpp
|
||||
base-stream.cpp
|
||||
base-string.cpp
|
||||
base-timer.cpp
|
||||
|
@ -90,7 +89,6 @@ add_boost_test(base
|
|||
base_serialize/object
|
||||
base_shellescape/escape_basic
|
||||
base_shellescape/escape_quoted
|
||||
base_stacktrace/stacktrace
|
||||
base_stream/readline_stdio
|
||||
base_string/construct
|
||||
base_string/equal
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
|
||||
|
||||
#include "base/stacktrace.hpp"
|
||||
#include <BoostTestTargetConfig.h>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(base_stacktrace)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(stacktrace)
|
||||
{
|
||||
StackTrace st;
|
||||
std::ostringstream obuf;
|
||||
obuf << st;
|
||||
BOOST_CHECK(obuf.str().size() > 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue