From d8a783a368cf2df4a2c7143cabd33cc134d6d79b Mon Sep 17 00:00:00 2001
From: Adam Heinermann <aheinerm@gmail.com>
Date: Wed, 17 Nov 2021 15:00:55 -0800
Subject: Fix crash on exit due to static scoped dummy threads

---
 src/core/hle/kernel/kernel.cpp | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

(limited to 'src/core/hle/kernel/kernel.cpp')

diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index e42a6d36fd..45e86a6774 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -300,15 +300,16 @@ struct KernelCore::Impl {
     // Gets the dummy KThread for the caller, allocating a new one if this is the first time
     KThread* GetHostDummyThread() {
         auto make_thread = [this]() {
-            std::unique_ptr<KThread> thread = std::make_unique<KThread>(system.Kernel());
+            std::lock_guard lk(dummy_thread_lock);
+            auto& thread = dummy_threads.emplace_back(std::make_unique<KThread>(system.Kernel()));
             KAutoObject::Create(thread.get());
             ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess());
             thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
-            return thread;
+            return thread.get();
         };
 
-        thread_local auto thread = make_thread();
-        return thread.get();
+        thread_local KThread* saved_thread = make_thread();
+        return saved_thread;
     }
 
     /// Registers a CPU core thread by allocating a host thread ID for it
@@ -695,6 +696,12 @@ struct KernelCore::Impl {
         return port;
     }
 
+    std::mutex server_ports_lock;
+    std::mutex server_sessions_lock;
+    std::mutex registered_objects_lock;
+    std::mutex registered_in_use_objects_lock;
+    std::mutex dummy_thread_lock;
+
     std::atomic<u32> next_object_id{0};
     std::atomic<u64> next_kernel_process_id{KProcess::InitialKIPIDMin};
     std::atomic<u64> next_user_process_id{KProcess::ProcessIDMin};
@@ -725,10 +732,6 @@ struct KernelCore::Impl {
     std::unordered_set<KServerSession*> server_sessions;
     std::unordered_set<KAutoObject*> registered_objects;
     std::unordered_set<KAutoObject*> registered_in_use_objects;
-    std::mutex server_ports_lock;
-    std::mutex server_sessions_lock;
-    std::mutex registered_objects_lock;
-    std::mutex registered_in_use_objects_lock;
 
     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
     std::vector<Kernel::PhysicalCore> cores;
@@ -753,6 +756,9 @@ struct KernelCore::Impl {
     std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
     std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
 
+    // Specifically tracked to be automatically destroyed with kernel
+    std::vector<std::unique_ptr<KThread>> dummy_threads;
+
     bool is_multicore{};
     bool is_phantom_mode_for_singlecore{};
     u32 single_core_thread_id{};
-- 
cgit v1.2.3-70-g09d2