From ceeda057981c4627470a4454603fbc3da19b74f8 Mon Sep 17 00:00:00 2001
From: SachinVin <26602104+SachinVin@users.noreply.github.com>
Date: Sun, 12 Nov 2023 01:25:42 +0530
Subject: [PATCH] assert/logging: Stop the logging thread and flush the
 backends before crashing (#7146)

---
 src/common/assert.h            |  5 +++++
 src/common/logging/backend.cpp | 17 +++++++++++++++++
 src/common/logging/backend.h   |  3 +++
 3 files changed, 25 insertions(+)

diff --git a/src/common/assert.h b/src/common/assert.h
index b5ec4fe47..5f632a5c6 100644
--- a/src/common/assert.h
+++ b/src/common/assert.h
@@ -6,6 +6,7 @@
 
 #include <cstdlib>
 #include "common/common_funcs.h"
+#include "common/logging/backend.h"
 #include "common/logging/log.h"
 
 // For asserts we'd like to keep all the junk executed when an assert happens away from the
@@ -17,6 +18,7 @@
         if (!(_a_)) [[unlikely]] {                                                                 \
             []() CITRA_NO_INLINE CITRA_NO_RETURN {                                                 \
                 LOG_CRITICAL(Debug, "Assertion Failed!");                                          \
+                Common::Log::Stop();                                                               \
                 Crash();                                                                           \
                 exit(1);                                                                           \
             }();                                                                                   \
@@ -28,6 +30,7 @@
         if (!(_a_)) [[unlikely]] {                                                                 \
             [&]() CITRA_NO_INLINE CITRA_NO_RETURN {                                                \
                 LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__);                            \
+                Common::Log::Stop();                                                               \
                 Crash();                                                                           \
                 exit(1);                                                                           \
             }();                                                                                   \
@@ -37,6 +40,7 @@
 #define UNREACHABLE()                                                                              \
     ([]() CITRA_NO_INLINE CITRA_NO_RETURN {                                                        \
         LOG_CRITICAL(Debug, "Unreachable code!");                                                  \
+        Common::Log::Stop();                                                                       \
         Crash();                                                                                   \
         exit(1);                                                                                   \
     }())
@@ -44,6 +48,7 @@
 #define UNREACHABLE_MSG(...)                                                                       \
     ([&]() CITRA_NO_INLINE CITRA_NO_RETURN {                                                       \
         LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__);                                    \
+        Common::Log::Stop();                                                                       \
         Crash();                                                                                   \
         exit(1);                                                                                   \
     }())
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index f39c79dea..1ea126eaa 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -220,6 +220,10 @@ public:
         instance->StartBackendThread();
     }
 
+    static void Stop() {
+        instance->StopBackendThread();
+    }
+
     Impl(const Impl&) = delete;
     Impl& operator=(const Impl&) = delete;
 
@@ -330,6 +334,15 @@ private:
         });
     }
 
+    void StopBackendThread() {
+        backend_thread.request_stop();
+        if (backend_thread.joinable()) {
+            backend_thread.join();
+        }
+
+        ForEachBackend([](Backend& backend) { backend.Flush(); });
+    }
+
     Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
                       const char* function, std::string&& message) const {
         using std::chrono::duration_cast;
@@ -421,6 +434,10 @@ void Start() {
     Impl::Start();
 }
 
+void Stop() {
+    Impl::Stop();
+}
+
 void DisableLoggingInTests() {
     initialization_in_progress_suppress_logging = true;
 }
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h
index 19a5ef0f4..8b664af36 100644
--- a/src/common/logging/backend.h
+++ b/src/common/logging/backend.h
@@ -16,6 +16,9 @@ void Initialize(std::string_view log_file = "");
 
 void Start();
 
+/// Explictily stops the logger thread and flushes the buffers
+void Stop();
+
 void DisableLoggingInTests();
 
 /**