Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Portable backtrace mechanism #59

Merged
merged 1 commit into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
cmnrd marked this conversation as resolved.
Show resolved Hide resolved
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++) {
cmnrd marked this conversation as resolved.
Show resolved Hide resolved
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
Loading