Skip to content

Commit

Permalink
Use backtrace_symbols() when printing stack traces on FreeBSD
Browse files Browse the repository at this point in the history
Unfortunately, the symbol resolution of boost::stacktrace is broken on
FreeBSD, therefore fall back to using backtrace_symbols() to print the
stack trace saved by Boost.

Additionally, -D_GNU_SOURCE is required on FreeBSD for the
_Unwind_Backtrace function used by boost::stacktrace.
  • Loading branch information
julianbrost committed Mar 1, 2021
1 parent 7d3885d commit b931194
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 3 deletions.
9 changes: 9 additions & 0 deletions CMakeLists.txt
Expand Up @@ -367,6 +367,15 @@ if(HAVE_LIBEXECINFO)
set(HAVE_BACKTRACE_SYMBOLS TRUE)
endif()

if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(ICINGA2_STACKTRACE_USE_BACKTRACE_SYMBOLS TRUE)
add_definitions(-D_GNU_SOURCE)
endif()

if(ICINGA2_STACKTRACE_USE_BACKTRACE_SYMBOLS AND NOT HAVE_BACKTRACE_SYMBOLS)
message(FATAL_ERROR "ICINGA2_STACKTRACE_USE_BACKTRACE_SYMBOLS is set but backtrace_symbols() was not found")
endif()

if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
exec_program(${CMAKE_CXX_COMPILER}
ARGS -dumpversion
Expand Down
1 change: 1 addition & 0 deletions config.h.cmake
Expand Up @@ -12,6 +12,7 @@
#cmakedefine HAVE_SYSTEMD

#cmakedefine ICINGA2_UNITY_BUILD
#cmakedefine ICINGA2_STACKTRACE_USE_BACKTRACE_SYMBOLS

#define ICINGA_CONFIGDIR "${ICINGA2_FULL_CONFIGDIR}"
#define ICINGA_DATADIR "${ICINGA2_FULL_DATADIR}"
Expand Down
1 change: 1 addition & 0 deletions lib/base/CMakeLists.txt
Expand Up @@ -64,6 +64,7 @@ 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
Expand Down
5 changes: 3 additions & 2 deletions lib/base/application.cpp
Expand Up @@ -2,6 +2,7 @@

#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"
Expand Down Expand Up @@ -763,7 +764,7 @@ void Application::SigAbrtHandler(int)

DisplayInfoMessage(ofs);

ofs << "\nStacktrace:\n" << boost::stacktrace::stacktrace() << "\n";
ofs << "\nStacktrace:\n" << StackTraceFormatter(boost::stacktrace::stacktrace()) << "\n";

DisplayBugMessage(ofs);

Expand Down Expand Up @@ -954,7 +955,7 @@ LONG CALLBACK Application::SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi)
<< " Flags: " << exi->ExceptionRecord->ExceptionFlags << "\n";
ofs.flags(savedflags);

ofs << "\nStacktrace:\n" << boost::stacktrace::stacktrace() << "\n";
ofs << "\nStacktrace:\n" << StackTraceFormatter(boost::stacktrace::stacktrace()) << "\n";

DisplayBugMessage(ofs);

Expand Down
3 changes: 2 additions & 1 deletion lib/base/exception.cpp
@@ -1,6 +1,7 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "base/exception.hpp"
#include "base/stacktrace.hpp"
#include <boost/thread/tss.hpp>
#include <utility>

Expand Down Expand Up @@ -248,7 +249,7 @@ String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, boo
}

if (st && !st->empty()) {
result << "\nStacktrace:\n" << *st;
result << "\nStacktrace:\n" << StackTraceFormatter(*st);
}
}

Expand Down
36 changes: 36 additions & 0 deletions lib/base/stacktrace.cpp
@@ -0,0 +1,36 @@
/* Icinga 2 | (c) 2020 Icinga GmbH | GPLv2+ */

#include <base/i2-base.hpp>
#include "base/stacktrace.hpp"
#include <iostream>
#include <iomanip>
#include <vector>

#ifdef HAVE_BACKTRACE_SYMBOLS
# include <execinfo.h>
#endif /* HAVE_BACKTRACE_SYMBOLS */

using namespace icinga;

std::ostream &icinga::operator<<(std::ostream &os, const StackTraceFormatter &f)
{
const boost::stacktrace::stacktrace &stack = f.m_Stack;

#ifdef ICINGA2_STACKTRACE_USE_BACKTRACE_SYMBOLS
std::vector<void *> addrs;
addrs.reserve(stack.size());
std::transform(stack.begin(), stack.end(), std::back_inserter(addrs), [](const boost::stacktrace::frame &f) {
return const_cast<void *>(f.address());
});

char **symbols = backtrace_symbols(addrs.data(), addrs.size());
for (size_t i = 0; i < addrs.size(); i++) {
os << std::setw(2) << i << "# " << symbols[i] << std::endl;
}
std::free(symbols);
#else /* ICINGA2_STACKTRACE_USE_BACKTRACE_SYMBOLS */
os << stack;
#endif /* ICINGA2_STACKTRACE_USE_BACKTRACE_SYMBOLS */

return os;
}
25 changes: 25 additions & 0 deletions lib/base/stacktrace.hpp
@@ -0,0 +1,25 @@
/* Icinga 2 | (c) 2020 Icinga GmbH | GPLv2+ */

#ifndef STACKTRACE_H
#define STACKTRACE_H

#include <boost/stacktrace.hpp>

namespace icinga
{

class StackTraceFormatter {
public:
StackTraceFormatter(const boost::stacktrace::stacktrace &stack) : m_Stack(stack) {}

private:
const boost::stacktrace::stacktrace &m_Stack;

friend std::ostream &operator<<(std::ostream &os, const StackTraceFormatter &f);
};

std::ostream& operator<<(std::ostream& os, const StackTraceFormatter &f);

}

#endif /* STACKTRACE_H */

0 comments on commit b931194

Please sign in to comment.