From ae390ad5a2571cec79d4a7a7b175ac4738e6c748 Mon Sep 17 00:00:00 2001
From: Jens Schmer <jens.schmer+git@gmail.com>
Date: Mon, 10 Dec 2018 19:42:01 +0100
Subject: [PATCH] Fix Process object leak on emulation stop

The Process object kept itself alive indefinitely because its handle_table
contains a SharedMemory object which owns a reference to the same Process object,
creating a circular ownership scenario.

Break that up by storing only a non-owning pointer in the SharedMemory object.
---
 src/core/hle/kernel/shared_memory.cpp |  6 +++---
 src/core/hle/kernel/shared_memory.h   |  6 +++---
 src/core/hle/kernel/svc.cpp           | 13 ++++++-------
 3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index d1ca60125..22d0c1dd5 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -17,13 +17,13 @@ namespace Kernel {
 SharedMemory::SharedMemory(KernelCore& kernel) : Object{kernel} {}
 SharedMemory::~SharedMemory() = default;
 
-SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, SharedPtr<Process> owner_process,
-                                             u64 size, MemoryPermission permissions,
+SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, Process* owner_process, u64 size,
+                                             MemoryPermission permissions,
                                              MemoryPermission other_permissions, VAddr address,
                                              MemoryRegion region, std::string name) {
     SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));
 
-    shared_memory->owner_process = std::move(owner_process);
+    shared_memory->owner_process = owner_process;
     shared_memory->name = std::move(name);
     shared_memory->size = size;
     shared_memory->permissions = permissions;
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 0b48db699..dab2a6bea 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -45,8 +45,8 @@ public:
      * linear heap.
      * @param name Optional object name, used for debugging purposes.
      */
-    static SharedPtr<SharedMemory> Create(KernelCore& kernel, SharedPtr<Process> owner_process,
-                                          u64 size, MemoryPermission permissions,
+    static SharedPtr<SharedMemory> Create(KernelCore& kernel, Process* owner_process, u64 size,
+                                          MemoryPermission permissions,
                                           MemoryPermission other_permissions, VAddr address = 0,
                                           MemoryRegion region = MemoryRegion::BASE,
                                           std::string name = "Unknown");
@@ -139,7 +139,7 @@ private:
     /// Permission restrictions applied to other processes mapping the block.
     MemoryPermission other_permissions{};
     /// Process that created this shared memory block.
-    SharedPtr<Process> owner_process;
+    Process* owner_process;
     /// Address of shared memory block in the owner process if specified.
     VAddr base_address = 0;
     /// Name of shared memory object.
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index f43c7201c..8b0b3671a 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1487,9 +1487,9 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
     }
 
     auto& kernel = Core::System::GetInstance().Kernel();
-    auto& handle_table = Core::CurrentProcess()->GetHandleTable();
-    const auto shared_mem_handle = SharedMemory::Create(
-        kernel, handle_table.Get<Process>(CurrentProcess), size, perms, perms, addr);
+    auto process = kernel.CurrentProcess();
+    auto& handle_table = process->GetHandleTable();
+    const auto shared_mem_handle = SharedMemory::Create(kernel, process, size, perms, perms, addr);
 
     CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
     return RESULT_SUCCESS;
@@ -1599,10 +1599,9 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
     }
 
     auto& kernel = Core::System::GetInstance().Kernel();
-    auto& handle_table = Core::CurrentProcess()->GetHandleTable();
-    auto shared_mem_handle =
-        SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
-                             local_perms, remote_perms);
+    auto process = kernel.CurrentProcess();
+    auto& handle_table = process->GetHandleTable();
+    auto shared_mem_handle = SharedMemory::Create(kernel, process, size, local_perms, remote_perms);
 
     CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
     return RESULT_SUCCESS;