Skip to content

Commit

Permalink
Portable backtrace mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
cmnrd committed Jul 23, 2024
1 parent cbb62dd commit dfdac2c
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 23 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ if (NOT DEFINED LF_REACTOR_CPP_SUFFIX)
endif()
endif()

find_package (Threads)
find_package(Threads)

find_package(Backtrace)
set(REACTOR_CPP_USE_BACKTRACE ${Backtrace_FOUND})

set(DEFAULT_BUILD_TYPE "Release")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
Expand Down
47 changes: 28 additions & 19 deletions include/reactor-cpp/assert.hh
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@
#include <stdexcept>
#include <string>

#ifdef __linux__
#include <execinfo.h>
#include <unistd.h>
#endif

#ifdef REACTOR_CPP_VALIDATE
constexpr bool runtime_validation = true;
#else
Expand All @@ -37,6 +32,33 @@ constexpr bool runtime_assertion = true;
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define reactor_assert(x) assert(x)

#ifdef REACTOR_CPP_USE_BACKTRACE

// NOLINTNEXTLINE
#include REACTOR_CPP_BACKTRACE_HEADER
#include <array>
#include <iostream>

namespace reactor {

constexpr std::size_t MAX_TRACE_SIZE{16};

inline void print_backtrace() {
std::array<void*, MAX_TRACE_SIZE> trace{nullptr};
int size = backtrace(trace.data(), MAX_TRACE_SIZE);
char** messages = backtrace_symbols(trace.data(), size);
for (int i{0}; i < size; i++) {
std::cerr << "[backtrace] " << messages[i] << '\n'; // NOLINT
}
}

} // namespace reactor
#else
namespace reactor {
inline void print_backtrace() {}
} // namespace reactor
#endif // REACTOR_CPP_BACKTRACE_SUPPORT

namespace reactor {

class ValidationError : public std::runtime_error {
Expand All @@ -48,23 +70,10 @@ public:
: std::runtime_error(build_message(msg)) {}
};

#ifdef __linux__
constexpr std::size_t MAX_STACK_SIZE{10};

inline void print_debug_backtrace() {
void* array[10]; // NOLINT
// get void*'s for all entries on the stack
int size = backtrace((void**)array, MAX_STACK_SIZE);
backtrace_symbols_fd((void**)array, size, STDERR_FILENO);
}
#endif

constexpr inline void validate([[maybe_unused]] bool condition, [[maybe_unused]] const std::string_view message) {
if constexpr (runtime_validation) { // NOLINT
if (!condition) {
#ifdef __linux__
print_debug_backtrace();
#endif
print_backtrace();
throw ValidationError(message);
}
}
Expand Down
3 changes: 3 additions & 0 deletions include/reactor-cpp/config.hh.in
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@
// NOLINTNEXTLINE
#cmakedefine REACTOR_CPP_LOG_LEVEL @REACTOR_CPP_LOG_LEVEL@

#cmakedefine REACTOR_CPP_USE_BACKTRACE
#define REACTOR_CPP_BACKTRACE_HEADER <@Backtrace_HEADER@>

#endif
5 changes: 5 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ else()
target_compile_options(${LIB_TARGET} PRIVATE -Wall -Wextra -pedantic -Werror)
endif()

if(${Backtrace_FOUND})
target_include_directories(${LIB_TARGET} PRIVATE ${Backtrace_INCLUDE_DIRS})
target_link_libraries(${LIB_TARGET} ${Backtrace_LIBRARY})
endif()

target_link_libraries(${LIB_TARGET} ${CMAKE_THREAD_LIBS_INIT})
if(REACTOR_CPP_TRACE)
target_link_libraries(${LIB_TARGET} LTTng::UST)
Expand Down
4 changes: 1 addition & 3 deletions lib/assert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ void assert_phase([[maybe_unused]] const ReactorElement* ptr, [[maybe_unused]] P
}
return "Unknown Phase: Value: " + std::to_string(extract_value(phase));
};
#ifdef __linux__
print_debug_backtrace();
#endif
print_backtrace();

// C++20 std::format
throw ValidationError("Expected Phase: " + enum_value_to_name(phase) +
Expand Down

0 comments on commit dfdac2c

Please # to comment.