diff options
author | bunnei <bunneidev@gmail.com> | 2021-11-02 04:11:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-02 04:11:30 +0100 |
commit | b118fa8698dbe0e2b6e663c1c37a7eac03422905 (patch) | |
tree | 14864116c00d385abba61ad2330c1c0f50e4b961 | |
parent | Merge pull request #7264 from zhaobot/tx-update-20211101021628 (diff) | |
parent | Fix dangling kernel objects when exiting (diff) | |
download | yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.gz yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.bz2 yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.lz yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.xz yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.tar.zst yuzu-b118fa8698dbe0e2b6e663c1c37a7eac03422905.zip |
-rw-r--r-- | src/core/core.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/kernel/k_handle_table.cpp | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/k_process.cpp | 11 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 36 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 6 |
6 files changed, 54 insertions, 24 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 3c75f42ae..c3a0f9dae 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -83,12 +83,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot( } } -void KProcessDeleter(Kernel::KProcess* process) { - process->Destroy(); -} - -using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>; - } // Anonymous namespace FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, @@ -261,11 +255,10 @@ struct System::Impl { } telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); - main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter}; - ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main", + auto main_process = Kernel::KProcess::Create(system.Kernel()); + ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", Kernel::KProcess::ProcessType::Userland) .IsSuccess()); - main_process->Open(); const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); if (load_result != Loader::ResultStatus::Success) { LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); @@ -275,7 +268,7 @@ struct System::Impl { static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); } AddGlueRegistrationForProcess(*app_loader, *main_process); - kernel.MakeCurrentProcess(main_process.get()); + kernel.MakeCurrentProcess(main_process); kernel.InitializeCores(); // Initialize cheat engine @@ -340,8 +333,6 @@ struct System::Impl { kernel.Shutdown(); memory.Reset(); applet_manager.ClearAll(); - // TODO: The main process should be freed based on KAutoObject ref counting. - main_process.reset(); LOG_DEBUG(Core, "Shutdown OK"); } @@ -403,7 +394,6 @@ struct System::Impl { std::unique_ptr<Tegra::GPU> gpu_core; std::unique_ptr<Hardware::InterruptManager> interrupt_manager; std::unique_ptr<Core::DeviceMemory> device_memory; - KProcessPtr main_process{nullptr, KProcessDeleter}; Core::Memory::Memory memory; CpuManager cpu_manager; std::atomic_bool is_powered_on{}; diff --git a/src/core/hle/kernel/k_handle_table.cpp b/src/core/hle/kernel/k_handle_table.cpp index 44d13169f..e90fc0628 100644 --- a/src/core/hle/kernel/k_handle_table.cpp +++ b/src/core/hle/kernel/k_handle_table.cpp @@ -56,6 +56,7 @@ bool KHandleTable::Remove(Handle handle) { } // Close the object. + kernel.UnregisterInUseObject(obj); obj->Close(); return true; } diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 211157ccc..76fd8c285 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -434,11 +434,6 @@ void KProcess::PrepareForTermination() { } void KProcess::Finalize() { - // Release memory to the resource limit. - if (resource_limit != nullptr) { - resource_limit->Close(); - } - // Finalize the handle table and close any open handles. handle_table.Finalize(); @@ -460,6 +455,12 @@ void KProcess::Finalize() { } } + // Release memory to the resource limit. + if (resource_limit != nullptr) { + resource_limit->Close(); + resource_limit = nullptr; + } + // Perform inherited finalization. KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index bea945301..4a139c5e7 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -91,12 +91,6 @@ struct KernelCore::Impl { } void Shutdown() { - // Shutdown all processes. - if (current_process) { - current_process->Finalize(); - current_process->Close(); - current_process = nullptr; - } process_list.clear(); // Close all open server ports. @@ -170,6 +164,24 @@ struct KernelCore::Impl { // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others next_host_thread_id = Core::Hardware::NUM_CPU_CORES; + // Close kernel objects that were not freed on shutdown + { + std::lock_guard lk(registered_in_use_objects_lock); + if (registered_in_use_objects.size()) { + for (auto& object : registered_in_use_objects) { + object->Close(); + } + registered_in_use_objects.clear(); + } + } + + // Shutdown all processes. + if (current_process) { + current_process->Finalize(); + current_process->Close(); + current_process = nullptr; + } + // Track kernel objects that were not freed on shutdown { std::lock_guard lk(registered_objects_lock); @@ -714,9 +726,11 @@ struct KernelCore::Impl { std::unordered_set<KServerPort*> server_ports; 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; @@ -928,6 +942,16 @@ void KernelCore::UnregisterKernelObject(KAutoObject* object) { impl->registered_objects.erase(object); } +void KernelCore::RegisterInUseObject(KAutoObject* object) { + std::lock_guard lk(impl->registered_in_use_objects_lock); + impl->registered_in_use_objects.insert(object); +} + +void KernelCore::UnregisterInUseObject(KAutoObject* object) { + std::lock_guard lk(impl->registered_in_use_objects_lock); + impl->registered_in_use_objects.erase(object); +} + bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { return port != impl->named_ports.cend(); } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b6658b437..d2ceae950 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -204,6 +204,14 @@ public: /// destroyed during the current emulation session. void UnregisterKernelObject(KAutoObject* object); + /// Registers kernel objects with guest in use state, this is purely for close + /// after emulation has been shutdown. + void RegisterInUseObject(KAutoObject* object); + + /// Unregisters a kernel object previously registered with RegisterInUseObject when it was + /// destroyed during the current emulation session. + void UnregisterInUseObject(KAutoObject* object); + /// Determines whether or not the given port is a valid named port. bool IsValidNamedPort(NamedPortTable::const_iterator port) const; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 7f38ade1c..c43135856 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -427,11 +427,15 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, num_handles), ResultInvalidHandle); + for (const auto& obj : objs) { + kernel.RegisterInUseObject(obj); + } } // Ensure handles are closed when we're done. SCOPE_EXIT({ for (u64 i = 0; i < num_handles; ++i) { + kernel.UnregisterInUseObject(objs[i]); objs[i]->Close(); } }); @@ -1561,6 +1565,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { // If we succeeded, persist a reference to the thread. thread->Open(); + system.Kernel().RegisterInUseObject(thread.GetPointerUnsafe()); return ResultSuccess; } @@ -1576,6 +1581,7 @@ static void ExitThread(Core::System& system) { auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); system.GlobalSchedulerContext().RemoveThread(current_thread); current_thread->Exit(); + system.Kernel().UnregisterInUseObject(current_thread); } static void ExitThread32(Core::System& system) { |