summaryrefslogtreecommitdiff
path: root/src/common/logging/backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/logging/backend.cpp')
-rw-r--r--src/common/logging/backend.cpp112
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
164bool initialization_in_progress_suppress_logging = true; 156bool 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