|
7 | 7 | #include <iostream> |
8 | 8 | #include <string_view> |
9 | 9 |
|
| 10 | +// boost is able to translate addresses |
| 11 | +// to lines with the following definition. |
| 12 | +// Similar to Seastar's seastar-addr2line |
10 | 13 | #define BOOST_STACKTRACE_USE_ADDR2LINE |
| 14 | + |
| 15 | +// Consider std once C++23 is available |
11 | 16 | #include <boost/stacktrace.hpp> |
| 17 | + |
12 | 18 | #include <seastar/core/reactor.hh> |
13 | 19 |
|
| 20 | +#include "crimson/common/log.h" |
| 21 | + |
14 | 22 | #include "common/safe_io.h" |
15 | 23 | #include "include/scope_guard.h" |
16 | 24 |
|
| 25 | +SET_SUBSYS(osd); |
| 26 | + |
17 | 27 | FatalSignal::FatalSignal() |
18 | 28 | { |
19 | 29 | install_oneshot_signals_handler<SIGSEGV, |
@@ -78,27 +88,40 @@ void FatalSignal::install_oneshot_signal_handler() |
78 | 88 | assert(r == 0); |
79 | 89 | } |
80 | 90 |
|
81 | | - |
82 | 91 | [[gnu::noinline]] static void print_backtrace(std::string_view cause) { |
83 | | - std::cerr << cause; |
84 | | - if (seastar::engine_is_ready()) { |
85 | | - std::cerr << " on shard " << seastar::this_shard_id(); |
86 | | - } |
87 | 92 | // nobody wants to see things like `FatalSignal::signaled()` or |
88 | 93 | // `print_backtrace()` in our backtraces. `+ 1` is for the extra |
89 | 94 | // frame created by kernel (signal trampoline, it will take care |
90 | 95 | // about e.g. sigreturn(2) calling; see the man page). |
91 | | - constexpr std::size_t FRAMES_TO_SKIP = 3 + 1; |
92 | | - std::cerr << ".\nBacktrace:\n"; |
93 | | - std::cerr << boost::stacktrace::stacktrace( |
| 96 | + constexpr std::size_t FRAMES_TO_SKIP = 2 + 1; |
| 97 | + |
| 98 | + // Let's inform regarding the abort before getting the stacktrace |
| 99 | + std::string pre_backtrace = fmt::format( |
| 100 | + "Aborting {} on shard {} - Stopping all shards", |
| 101 | + cause, |
| 102 | + seastar::engine_is_ready() ? std::to_string(seastar::this_shard_id()) : "no shard"); |
| 103 | + |
| 104 | + GENERIC_ERROR("{}", pre_backtrace); |
| 105 | + std::cerr << pre_backtrace << std::flush; |
| 106 | + |
| 107 | + seastar::engine().exit(1); |
| 108 | + |
| 109 | + std::string backtrace = fmt::format("{} on shard {} \nBacktrace:\n {}", |
| 110 | + cause, |
| 111 | + seastar::engine_is_ready() ? std::to_string(seastar::this_shard_id()) : "no shard", |
| 112 | + boost::stacktrace::to_string(boost::stacktrace::stacktrace( |
94 | 113 | FRAMES_TO_SKIP, |
95 | | - static_cast<std::size_t>(-1)/* max depth same as the default one */); |
96 | | - std::cerr << std::flush; |
| 114 | + static_cast<std::size_t>(-1)/* max depth same as the default one */))); |
| 115 | + |
| 116 | + // Print backtrace in log and in std out |
| 117 | + GENERIC_ERROR("{}", backtrace); |
| 118 | + std::cerr << backtrace << std::flush; |
| 119 | + |
97 | 120 | // TODO: dump crash related meta data to $crash_dir |
98 | 121 | // see handle_fatal_signal() |
99 | 122 | } |
100 | 123 |
|
101 | | -static void print_segv_info(const siginfo_t& siginfo) |
| 124 | +[[maybe_unused]] static void print_segv_info(const siginfo_t& siginfo) |
102 | 125 | { |
103 | 126 | std::cerr \ |
104 | 127 | << "Dump of siginfo:" << std::endl |
@@ -127,7 +150,7 @@ static void print_segv_info(const siginfo_t& siginfo) |
127 | 150 | std::cerr << std::flush; |
128 | 151 | } |
129 | 152 |
|
130 | | -static void print_proc_maps() |
| 153 | +[[maybe_unused]] static void print_proc_maps() |
131 | 154 | { |
132 | 155 | const int fd = ::open("/proc/self/maps", O_RDONLY); |
133 | 156 | if (fd < 0) { |
@@ -156,17 +179,20 @@ static void print_proc_maps() |
156 | 179 | [[gnu::noinline]] void FatalSignal::signaled(const int signum, |
157 | 180 | const siginfo_t& siginfo) |
158 | 181 | { |
| 182 | + // Commented out for clean backtrace logs, |
| 183 | + // can be used if needed: |
| 184 | + // print_proc_maps(); |
| 185 | + // print_segv_info(siginfo); |
| 186 | + |
159 | 187 | switch (signum) { |
160 | 188 | case SIGSEGV: |
161 | | - print_backtrace("Segmentation fault"); |
162 | | - print_segv_info(siginfo); |
| 189 | + print_backtrace("Got SIGSEGV"); |
163 | 190 | break; |
164 | 191 | case SIGABRT: |
165 | | - print_backtrace("Aborting"); |
| 192 | + print_backtrace("Got SIGABRT"); |
166 | 193 | break; |
167 | 194 | default: |
168 | | - print_backtrace(fmt::format("Signal {}", signum)); |
| 195 | + print_backtrace(fmt::format("Got signal {}", signum)); |
169 | 196 | break; |
170 | 197 | } |
171 | | - print_proc_maps(); |
172 | 198 | } |
0 commit comments