diff options
Diffstat (limited to 'src/common/logging/backend.cpp')
| -rw-r--r-- | src/common/logging/backend.cpp | 112 |
1 files changed, 1 insertions, 111 deletions
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 6f1d251e1..949384fd3 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -13,14 +13,6 @@ | |||
| 13 | #include <windows.h> // For OutputDebugStringW | 13 | #include <windows.h> // For OutputDebugStringW |
| 14 | #endif | 14 | #endif |
| 15 | 15 | ||
| 16 | #if defined(__linux__) && defined(__GNUG__) && !defined(__clang__) | ||
| 17 | #define BOOST_STACKTRACE_USE_BACKTRACE | ||
| 18 | #include <boost/stacktrace.hpp> | ||
| 19 | #undef BOOST_STACKTRACE_USE_BACKTRACE | ||
| 20 | #include <signal.h> | ||
| 21 | #define YUZU_LINUX_GCC_BACKTRACE | ||
| 22 | #endif | ||
| 23 | |||
| 24 | #include "common/fs/file.h" | 16 | #include "common/fs/file.h" |
| 25 | #include "common/fs/fs.h" | 17 | #include "common/fs/fs.h" |
| 26 | #include "common/fs/fs_paths.h" | 18 | #include "common/fs/fs_paths.h" |
| @@ -163,14 +155,6 @@ public: | |||
| 163 | 155 | ||
| 164 | bool initialization_in_progress_suppress_logging = true; | 156 | bool initialization_in_progress_suppress_logging = true; |
| 165 | 157 | ||
| 166 | #ifdef YUZU_LINUX_GCC_BACKTRACE | ||
| 167 | [[noreturn]] void SleepForever() { | ||
| 168 | while (true) { | ||
| 169 | pause(); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | #endif | ||
| 173 | |||
| 174 | /** | 158 | /** |
| 175 | * Static state as a singleton. | 159 | * Static state as a singleton. |
| 176 | */ | 160 | */ |
| @@ -242,66 +226,9 @@ private: | |||
| 242 | while (max_logs_to_write-- && message_queue.Pop(entry)) { | 226 | while (max_logs_to_write-- && message_queue.Pop(entry)) { |
| 243 | write_logs(); | 227 | write_logs(); |
| 244 | } | 228 | } |
| 245 | })} { | 229 | })} {} |
| 246 | #ifdef YUZU_LINUX_GCC_BACKTRACE | ||
| 247 | int waker_pipefd[2]; | ||
| 248 | int done_printing_pipefd[2]; | ||
| 249 | if (pipe2(waker_pipefd, O_CLOEXEC) || pipe2(done_printing_pipefd, O_CLOEXEC)) { | ||
| 250 | abort(); | ||
| 251 | } | ||
| 252 | backtrace_thread_waker_fd = waker_pipefd[1]; | ||
| 253 | backtrace_done_printing_fd = done_printing_pipefd[0]; | ||
| 254 | std::thread([this, wait_fd = waker_pipefd[0], done_fd = done_printing_pipefd[1]] { | ||
| 255 | Common::SetCurrentThreadName("yuzu:Crash"); | ||
| 256 | for (u8 ignore = 0; read(wait_fd, &ignore, 1) != 1;) | ||
| 257 | ; | ||
| 258 | const int sig = received_signal; | ||
| 259 | if (sig <= 0) { | ||
| 260 | abort(); | ||
| 261 | } | ||
| 262 | StopBackendThread(); | ||
| 263 | const auto signal_entry = | ||
| 264 | CreateEntry(Class::Log, Level::Critical, "?", 0, "?", | ||
| 265 | fmt::vformat("Received signal {}", fmt::make_format_args(sig))); | ||
| 266 | ForEachBackend([&signal_entry](Backend& backend) { | ||
| 267 | backend.EnableForStacktrace(); | ||
| 268 | backend.Write(signal_entry); | ||
| 269 | }); | ||
| 270 | const auto backtrace = | ||
| 271 | boost::stacktrace::stacktrace::from_dump(backtrace_storage.data(), 4096); | ||
| 272 | for (const auto& frame : backtrace.as_vector()) { | ||
| 273 | auto line = boost::stacktrace::detail::to_string(&frame, 1); | ||
| 274 | if (line.empty()) { | ||
| 275 | abort(); | ||
| 276 | } | ||
| 277 | line.pop_back(); // Remove newline | ||
| 278 | const auto frame_entry = | ||
| 279 | CreateEntry(Class::Log, Level::Critical, "?", 0, "?", line); | ||
| 280 | ForEachBackend([&frame_entry](Backend& backend) { backend.Write(frame_entry); }); | ||
| 281 | } | ||
| 282 | using namespace std::literals; | ||
| 283 | const auto rip_entry = CreateEntry(Class::Log, Level::Critical, "?", 0, "?", "RIP"s); | ||
| 284 | ForEachBackend([&rip_entry](Backend& backend) { | ||
| 285 | backend.Write(rip_entry); | ||
| 286 | backend.Flush(); | ||
| 287 | }); | ||
| 288 | for (const u8 anything = 0; write(done_fd, &anything, 1) != 1;) | ||
| 289 | ; | ||
| 290 | // Abort on original thread to help debugging | ||
| 291 | SleepForever(); | ||
| 292 | }).detach(); | ||
| 293 | signal(SIGSEGV, &HandleSignal); | ||
| 294 | signal(SIGABRT, &HandleSignal); | ||
| 295 | #endif | ||
| 296 | } | ||
| 297 | 230 | ||
| 298 | ~Impl() { | 231 | ~Impl() { |
| 299 | #ifdef YUZU_LINUX_GCC_BACKTRACE | ||
| 300 | if (int zero_or_ignore = 0; | ||
| 301 | !received_signal.compare_exchange_strong(zero_or_ignore, SIGKILL)) { | ||
| 302 | SleepForever(); | ||
| 303 | } | ||
| 304 | #endif | ||
| 305 | StopBackendThread(); | 232 | StopBackendThread(); |
| 306 | } | 233 | } |
| 307 | 234 | ||
| @@ -340,36 +267,6 @@ private: | |||
| 340 | delete ptr; | 267 | delete ptr; |
| 341 | } | 268 | } |
| 342 | 269 | ||
| 343 | #ifdef YUZU_LINUX_GCC_BACKTRACE | ||
| 344 | [[noreturn]] static void HandleSignal(int sig) { | ||
| 345 | signal(SIGABRT, SIG_DFL); | ||
| 346 | signal(SIGSEGV, SIG_DFL); | ||
| 347 | if (sig <= 0) { | ||
| 348 | abort(); | ||
| 349 | } | ||
| 350 | instance->InstanceHandleSignal(sig); | ||
| 351 | } | ||
| 352 | |||
| 353 | [[noreturn]] void InstanceHandleSignal(int sig) { | ||
| 354 | if (int zero_or_ignore = 0; !received_signal.compare_exchange_strong(zero_or_ignore, sig)) { | ||
| 355 | if (received_signal == SIGKILL) { | ||
| 356 | abort(); | ||
| 357 | } | ||
| 358 | SleepForever(); | ||
| 359 | } | ||
| 360 | // Don't restart like boost suggests. We want to append to the log file and not lose dynamic | ||
| 361 | // symbols. This may segfault if it unwinds outside C/C++ code but we'll just have to fall | ||
| 362 | // back to core dumps. | ||
| 363 | boost::stacktrace::safe_dump_to(backtrace_storage.data(), 4096); | ||
| 364 | std::atomic_thread_fence(std::memory_order_seq_cst); | ||
| 365 | for (const int anything = 0; write(backtrace_thread_waker_fd, &anything, 1) != 1;) | ||
| 366 | ; | ||
| 367 | for (u8 ignore = 0; read(backtrace_done_printing_fd, &ignore, 1) != 1;) | ||
| 368 | ; | ||
| 369 | abort(); | ||
| 370 | } | ||
| 371 | #endif | ||
| 372 | |||
| 373 | static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter}; | 270 | static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter}; |
| 374 | 271 | ||
| 375 | Filter filter; | 272 | Filter filter; |
| @@ -380,13 +277,6 @@ private: | |||
| 380 | std::thread backend_thread; | 277 | std::thread backend_thread; |
| 381 | MPSCQueue<Entry> message_queue{}; | 278 | MPSCQueue<Entry> message_queue{}; |
| 382 | std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; | 279 | std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; |
| 383 | |||
| 384 | #ifdef YUZU_LINUX_GCC_BACKTRACE | ||
| 385 | std::atomic_int received_signal{0}; | ||
| 386 | std::array<u8, 4096> backtrace_storage{}; | ||
| 387 | int backtrace_thread_waker_fd; | ||
| 388 | int backtrace_done_printing_fd; | ||
| 389 | #endif | ||
| 390 | }; | 280 | }; |
| 391 | } // namespace | 281 | } // namespace |
| 392 | 282 | ||