diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 4729a7fe0..64166ab99 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -37,6 +37,10 @@ void Thread::Acquire() {
     ASSERT_MSG(!ShouldWait(), "object unavailable!");
 }
 
+// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
+//               us to simply use a pool index or similar.
+static Kernel::HandleTable wakeup_callback_handle_table;
+
 // Lists all thread ids that aren't deleted/etc.
 static std::vector<SharedPtr<Thread>> thread_list;
 
@@ -93,6 +97,8 @@ void Thread::Stop() {
 
     // Cancel any outstanding wakeup events for this thread
     CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
+    wakeup_callback_handle_table.Close(callback_handle);
+    callback_handle = 0;
 
     // Clean up thread from ready queue
     // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
@@ -108,6 +114,7 @@ void Thread::Stop() {
     for (auto& wait_object : wait_objects) {
         wait_object->RemoveWaitingThread(this);
     }
+    wait_objects.clear();
 
     Kernel::g_current_process->used_tls_slots[tls_index] = false;
 
@@ -268,10 +275,6 @@ void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) {
     thread->status = THREADSTATUS_WAIT_ARB;
 }
 
-// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
-//               us to simply use a pool index or similar.
-static Kernel::HandleTable wakeup_callback_handle_table;
-
 /**
  * Callback that will wake up the thread it was scheduled for
  * @param thread_handle The handle of the thread that's been awoken
@@ -503,12 +506,16 @@ void ThreadingInit() {
 
     current_thread = nullptr;
     next_thread_id = 1;
+}
 
+void ThreadingShutdown() {
+    current_thread = nullptr;
+
+    for (auto& t : thread_list) {
+        t->Stop();
+    }
     thread_list.clear();
     ready_queue.clear();
 }
 
-void ThreadingShutdown() {
-}
-
 } // namespace
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index b364beed9..7b6ab4ce0 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -406,6 +406,9 @@ void Shutdown() {
     lock = nullptr;
     notification_event = nullptr;
     parameter_event = nullptr;
+
+    next_parameter.object = nullptr;
+
     HLE::Applets::Shutdown();
 }
 
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index fafb43a2f..a8cb15d60 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -310,4 +310,9 @@ Interface::Interface() {
     Register(FunctionTable);
 }
 
+Interface::~Interface() {
+    semaphore_event = nullptr;
+    interrupt_event = nullptr;
+}
+
 } // namespace
diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h
index 54109b2a9..b6f611db5 100644
--- a/src/core/hle/service/dsp_dsp.h
+++ b/src/core/hle/service/dsp_dsp.h
@@ -16,6 +16,7 @@ namespace DSP_DSP {
 class Interface : public Service::Interface {
 public:
     Interface();
+    ~Interface() override;
 
     std::string GetPortName() const override {
         return "dsp::DSP";
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 3910d0227..8b40ba376 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -584,7 +584,7 @@ const Interface::FunctionInfo FunctionTable[] = {
 Interface::Interface() {
     Register(FunctionTable);
 
-    g_interrupt_event = 0;
+    g_interrupt_event = nullptr;
 
     using Kernel::MemoryPermission;
     g_shared_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite,
@@ -593,4 +593,9 @@ Interface::Interface() {
     g_thread_id = 0;
 }
 
+Interface::~Interface() {
+    g_interrupt_event = nullptr;
+    g_shared_memory = nullptr;
+}
+
 } // namespace
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 268089fdd..c89d0a467 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -161,6 +161,7 @@ static_assert(sizeof(CommandBuffer) == 0x200, "CommandBuffer struct has incorrec
 class Interface : public Service::Interface {
 public:
     Interface();
+    ~Interface() override;
 
     std::string GetPortName() const override {
         return "gsp::Gpu";
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index 25b01860e..18b22956f 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -125,4 +125,8 @@ Interface::Interface() {
     Register(FunctionTable);
 }
 
+Interface::~Interface() {
+    handle_event = nullptr;
+}
+
 } // namespace
diff --git a/src/core/hle/service/nwm_uds.h b/src/core/hle/service/nwm_uds.h
index 82abdff28..0ced2359c 100644
--- a/src/core/hle/service/nwm_uds.h
+++ b/src/core/hle/service/nwm_uds.h
@@ -16,6 +16,7 @@ namespace NWM_UDS {
 class Interface : public Service::Interface {
 public:
     Interface();
+    ~Interface() override;
 
     std::string GetPortName() const override {
         return "nwm::UDS";
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 6c49fa6cf..3b8c7c0e4 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -68,4 +68,8 @@ Interface::Interface() {
     Register(FunctionTable);
 }
 
+Interface::~Interface() {
+    event_handle = nullptr;
+}
+
 } // namespace
diff --git a/src/core/hle/service/srv.h b/src/core/hle/service/srv.h
index 653aba5cb..96c89b025 100644
--- a/src/core/hle/service/srv.h
+++ b/src/core/hle/service/srv.h
@@ -13,6 +13,7 @@ namespace SRV {
 class Interface : public Service::Interface {
 public:
     Interface();
+    ~Interface() override;
 
     std::string GetPortName() const override {
         return "srv:";
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index e121a54e3..6e7dafaad 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -410,4 +410,8 @@ Interface::Interface() {
     Register(FunctionTable);
 }
 
+Interface::~Interface() {
+    completion_event = nullptr;
+}
+
 } // namespace
diff --git a/src/core/hle/service/y2r_u.h b/src/core/hle/service/y2r_u.h
index 9454e5aab..3965a5545 100644
--- a/src/core/hle/service/y2r_u.h
+++ b/src/core/hle/service/y2r_u.h
@@ -112,6 +112,7 @@ struct ConversionConfiguration {
 class Interface : public Service::Interface {
 public:
     Interface();
+    ~Interface() override;
 
     std::string GetPortName() const override {
         return "y2r:u";