Merge pull request #7091 from vonchenplus/fix_memroy_leak
core: Fix memory leak
This commit is contained in:
		@@ -216,6 +216,7 @@ add_library(core STATIC
 | 
			
		||||
    hle/kernel/k_session.h
 | 
			
		||||
    hle/kernel/k_shared_memory.cpp
 | 
			
		||||
    hle/kernel/k_shared_memory.h
 | 
			
		||||
    hle/kernel/k_shared_memory_info.h
 | 
			
		||||
    hle/kernel/k_slab_heap.h
 | 
			
		||||
    hle/kernel/k_spin_lock.cpp
 | 
			
		||||
    hle/kernel/k_spin_lock.h
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@
 | 
			
		||||
#include "core/hle/kernel/k_scheduler.h"
 | 
			
		||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
 | 
			
		||||
#include "core/hle/kernel/k_shared_memory.h"
 | 
			
		||||
#include "core/hle/kernel/k_shared_memory_info.h"
 | 
			
		||||
#include "core/hle/kernel/k_slab_heap.h"
 | 
			
		||||
#include "core/hle/kernel/k_thread.h"
 | 
			
		||||
#include "core/hle/kernel/kernel.h"
 | 
			
		||||
@@ -254,10 +255,26 @@ ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAdd
 | 
			
		||||
    // Lock ourselves, to prevent concurrent access.
 | 
			
		||||
    KScopedLightLock lk(state_lock);
 | 
			
		||||
 | 
			
		||||
    // TODO(bunnei): Manage KSharedMemoryInfo list here.
 | 
			
		||||
    // Try to find an existing info for the memory.
 | 
			
		||||
    KSharedMemoryInfo* shemen_info = nullptr;
 | 
			
		||||
    const auto iter = std::find_if(
 | 
			
		||||
        shared_memory_list.begin(), shared_memory_list.end(),
 | 
			
		||||
        [shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; });
 | 
			
		||||
    if (iter != shared_memory_list.end()) {
 | 
			
		||||
        shemen_info = *iter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Open a reference to the shared memory.
 | 
			
		||||
    if (shemen_info == nullptr) {
 | 
			
		||||
        shemen_info = KSharedMemoryInfo::Allocate(kernel);
 | 
			
		||||
        R_UNLESS(shemen_info != nullptr, ResultOutOfMemory);
 | 
			
		||||
 | 
			
		||||
        shemen_info->Initialize(shmem);
 | 
			
		||||
        shared_memory_list.push_back(shemen_info);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Open a reference to the shared memory and its info.
 | 
			
		||||
    shmem->Open();
 | 
			
		||||
    shemen_info->Open();
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
@@ -267,7 +284,20 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr a
 | 
			
		||||
    // Lock ourselves, to prevent concurrent access.
 | 
			
		||||
    KScopedLightLock lk(state_lock);
 | 
			
		||||
 | 
			
		||||
    // TODO(bunnei): Manage KSharedMemoryInfo list here.
 | 
			
		||||
    KSharedMemoryInfo* shemen_info = nullptr;
 | 
			
		||||
    const auto iter = std::find_if(
 | 
			
		||||
        shared_memory_list.begin(), shared_memory_list.end(),
 | 
			
		||||
        [shmem](const KSharedMemoryInfo* info) { return info->GetSharedMemory() == shmem; });
 | 
			
		||||
    if (iter != shared_memory_list.end()) {
 | 
			
		||||
        shemen_info = *iter;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ASSERT(shemen_info != nullptr);
 | 
			
		||||
 | 
			
		||||
    if (shemen_info->Close()) {
 | 
			
		||||
        shared_memory_list.erase(iter);
 | 
			
		||||
        KSharedMemoryInfo::Free(kernel, shemen_info);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Close a reference to the shared memory.
 | 
			
		||||
    shmem->Close();
 | 
			
		||||
@@ -412,6 +442,24 @@ void KProcess::Finalize() {
 | 
			
		||||
    // Finalize the handle table and close any open handles.
 | 
			
		||||
    handle_table.Finalize();
 | 
			
		||||
 | 
			
		||||
    // Free all shared memory infos.
 | 
			
		||||
    {
 | 
			
		||||
        auto it = shared_memory_list.begin();
 | 
			
		||||
        while (it != shared_memory_list.end()) {
 | 
			
		||||
            KSharedMemoryInfo* info = *it;
 | 
			
		||||
            KSharedMemory* shmem = info->GetSharedMemory();
 | 
			
		||||
 | 
			
		||||
            while (!info->Close()) {
 | 
			
		||||
                shmem->Close();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            shmem->Close();
 | 
			
		||||
 | 
			
		||||
            it = shared_memory_list.erase(it);
 | 
			
		||||
            KSharedMemoryInfo::Free(kernel, info);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Perform inherited finalization.
 | 
			
		||||
    KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ class KernelCore;
 | 
			
		||||
class KPageTable;
 | 
			
		||||
class KResourceLimit;
 | 
			
		||||
class KThread;
 | 
			
		||||
class KSharedMemoryInfo;
 | 
			
		||||
class TLSPage;
 | 
			
		||||
 | 
			
		||||
struct CodeSet;
 | 
			
		||||
@@ -448,6 +449,9 @@ private:
 | 
			
		||||
    /// List of threads that are running with this process as their owner.
 | 
			
		||||
    std::list<const KThread*> thread_list;
 | 
			
		||||
 | 
			
		||||
    /// List of shared memory that are running with this process as their owner.
 | 
			
		||||
    std::list<KSharedMemoryInfo*> shared_memory_list;
 | 
			
		||||
 | 
			
		||||
    /// Address of the top of the main thread's stack
 | 
			
		||||
    VAddr main_thread_stack_top{};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								src/core/hle/kernel/k_shared_memory_info.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/core/hle/kernel/k_shared_memory_info.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// Copyright 2021 yuzu Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include <boost/intrusive/list.hpp>
 | 
			
		||||
 | 
			
		||||
#include "common/assert.h"
 | 
			
		||||
#include "core/hle/kernel/slab_helpers.h"
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
 | 
			
		||||
class KSharedMemory;
 | 
			
		||||
 | 
			
		||||
class KSharedMemoryInfo final : public KSlabAllocated<KSharedMemoryInfo>,
 | 
			
		||||
                                public boost::intrusive::list_base_hook<> {
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit KSharedMemoryInfo() = default;
 | 
			
		||||
 | 
			
		||||
    constexpr void Initialize(KSharedMemory* shmem) {
 | 
			
		||||
        shared_memory = shmem;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constexpr KSharedMemory* GetSharedMemory() const {
 | 
			
		||||
        return shared_memory;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constexpr void Open() {
 | 
			
		||||
        ++reference_count;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constexpr bool Close() {
 | 
			
		||||
        return (--reference_count) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    KSharedMemory* shared_memory{};
 | 
			
		||||
    size_t reference_count{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Kernel
 | 
			
		||||
@@ -49,6 +49,7 @@ class KScheduler;
 | 
			
		||||
class KServerSession;
 | 
			
		||||
class KSession;
 | 
			
		||||
class KSharedMemory;
 | 
			
		||||
class KSharedMemoryInfo;
 | 
			
		||||
class KThread;
 | 
			
		||||
class KTransferMemory;
 | 
			
		||||
class KWritableEvent;
 | 
			
		||||
@@ -309,6 +310,8 @@ public:
 | 
			
		||||
            return slab_heap_container->session;
 | 
			
		||||
        } else if constexpr (std::is_same_v<T, KSharedMemory>) {
 | 
			
		||||
            return slab_heap_container->shared_memory;
 | 
			
		||||
        } else if constexpr (std::is_same_v<T, KSharedMemoryInfo>) {
 | 
			
		||||
            return slab_heap_container->shared_memory_info;
 | 
			
		||||
        } else if constexpr (std::is_same_v<T, KThread>) {
 | 
			
		||||
            return slab_heap_container->thread;
 | 
			
		||||
        } else if constexpr (std::is_same_v<T, KTransferMemory>) {
 | 
			
		||||
@@ -362,6 +365,7 @@ private:
 | 
			
		||||
        KSlabHeap<KResourceLimit> resource_limit;
 | 
			
		||||
        KSlabHeap<KSession> session;
 | 
			
		||||
        KSlabHeap<KSharedMemory> shared_memory;
 | 
			
		||||
        KSlabHeap<KSharedMemoryInfo> shared_memory_info;
 | 
			
		||||
        KSlabHeap<KThread> thread;
 | 
			
		||||
        KSlabHeap<KTransferMemory> transfer_memory;
 | 
			
		||||
        KSlabHeap<KWritableEvent> writeable_event;
 | 
			
		||||
 
 | 
			
		||||
@@ -320,17 +320,19 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
 | 
			
		||||
 | 
			
		||||
    auto& kernel = system.Kernel();
 | 
			
		||||
 | 
			
		||||
    KScopedAutoObject session =
 | 
			
		||||
        kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
 | 
			
		||||
    R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
    LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
 | 
			
		||||
 | 
			
		||||
    auto thread = kernel.CurrentScheduler()->GetCurrentThread();
 | 
			
		||||
    {
 | 
			
		||||
        KScopedSchedulerLock lock(kernel);
 | 
			
		||||
        thread->SetState(ThreadState::Waiting);
 | 
			
		||||
        thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
 | 
			
		||||
        session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            KScopedAutoObject session =
 | 
			
		||||
                kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
 | 
			
		||||
            R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
 | 
			
		||||
            LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
 | 
			
		||||
            session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KSynchronizationObject* dummy{};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user