Skip to content

Commit dfdac2c

Browse files
committed
Portable backtrace mechanism
1 parent cbb62dd commit dfdac2c

File tree

5 files changed

+41
-23
lines changed

5 files changed

+41
-23
lines changed

CMakeLists.txt

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ if (NOT DEFINED LF_REACTOR_CPP_SUFFIX)
3030
endif()
3131
endif()
3232

33-
find_package (Threads)
33+
find_package(Threads)
34+
35+
find_package(Backtrace)
36+
set(REACTOR_CPP_USE_BACKTRACE ${Backtrace_FOUND})
3437

3538
set(DEFAULT_BUILD_TYPE "Release")
3639
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)

include/reactor-cpp/assert.hh

+28-19
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,6 @@
1717
#include <stdexcept>
1818
#include <string>
1919

20-
#ifdef __linux__
21-
#include <execinfo.h>
22-
#include <unistd.h>
23-
#endif
24-
2520
#ifdef REACTOR_CPP_VALIDATE
2621
constexpr bool runtime_validation = true;
2722
#else
@@ -37,6 +32,33 @@ constexpr bool runtime_assertion = true;
3732
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
3833
#define reactor_assert(x) assert(x)
3934

35+
#ifdef REACTOR_CPP_USE_BACKTRACE
36+
37+
// NOLINTNEXTLINE
38+
#include REACTOR_CPP_BACKTRACE_HEADER
39+
#include <array>
40+
#include <iostream>
41+
42+
namespace reactor {
43+
44+
constexpr std::size_t MAX_TRACE_SIZE{16};
45+
46+
inline void print_backtrace() {
47+
std::array<void*, MAX_TRACE_SIZE> trace{nullptr};
48+
int size = backtrace(trace.data(), MAX_TRACE_SIZE);
49+
char** messages = backtrace_symbols(trace.data(), size);
50+
for (int i{0}; i < size; i++) {
51+
std::cerr << "[backtrace] " << messages[i] << '\n'; // NOLINT
52+
}
53+
}
54+
55+
} // namespace reactor
56+
#else
57+
namespace reactor {
58+
inline void print_backtrace() {}
59+
} // namespace reactor
60+
#endif // REACTOR_CPP_BACKTRACE_SUPPORT
61+
4062
namespace reactor {
4163

4264
class ValidationError : public std::runtime_error {
@@ -48,23 +70,10 @@ public:
4870
: std::runtime_error(build_message(msg)) {}
4971
};
5072

51-
#ifdef __linux__
52-
constexpr std::size_t MAX_STACK_SIZE{10};
53-
54-
inline void print_debug_backtrace() {
55-
void* array[10]; // NOLINT
56-
// get void*'s for all entries on the stack
57-
int size = backtrace((void**)array, MAX_STACK_SIZE);
58-
backtrace_symbols_fd((void**)array, size, STDERR_FILENO);
59-
}
60-
#endif
61-
6273
constexpr inline void validate([[maybe_unused]] bool condition, [[maybe_unused]] const std::string_view message) {
6374
if constexpr (runtime_validation) { // NOLINT
6475
if (!condition) {
65-
#ifdef __linux__
66-
print_debug_backtrace();
67-
#endif
76+
print_backtrace();
6877
throw ValidationError(message);
6978
}
7079
}

include/reactor-cpp/config.hh.in

+3
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,7 @@
1010
// NOLINTNEXTLINE
1111
#cmakedefine REACTOR_CPP_LOG_LEVEL @REACTOR_CPP_LOG_LEVEL@
1212

13+
#cmakedefine REACTOR_CPP_USE_BACKTRACE
14+
#define REACTOR_CPP_BACKTRACE_HEADER <@Backtrace_HEADER@>
15+
1316
#endif

lib/CMakeLists.txt

+5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ else()
3636
target_compile_options(${LIB_TARGET} PRIVATE -Wall -Wextra -pedantic -Werror)
3737
endif()
3838

39+
if(${Backtrace_FOUND})
40+
target_include_directories(${LIB_TARGET} PRIVATE ${Backtrace_INCLUDE_DIRS})
41+
target_link_libraries(${LIB_TARGET} ${Backtrace_LIBRARY})
42+
endif()
43+
3944
target_link_libraries(${LIB_TARGET} ${CMAKE_THREAD_LIBS_INIT})
4045
if(REACTOR_CPP_TRACE)
4146
target_link_libraries(${LIB_TARGET} LTTng::UST)

lib/assert.cc

+1-3
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ void assert_phase([[maybe_unused]] const ReactorElement* ptr, [[maybe_unused]] P
3333
}
3434
return "Unknown Phase: Value: " + std::to_string(extract_value(phase));
3535
};
36-
#ifdef __linux__
37-
print_debug_backtrace();
38-
#endif
36+
print_backtrace();
3937

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

0 commit comments

Comments
 (0)