mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-11-01 07:16:42 +08:00 
			
		
		
		
	Merge pull request #7227 from vonchenplus/fix_memory_leak_v2
Fix memory leak v2
This commit is contained in:
		
						commit
						b118fa8698
					
				| @ -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
 | } // Anonymous namespace
 | ||||||
| 
 | 
 | ||||||
| FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | ||||||
| @ -261,11 +255,10 @@ struct System::Impl { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); |         telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); | ||||||
|         main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter}; |         auto main_process = Kernel::KProcess::Create(system.Kernel()); | ||||||
|         ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main", |         ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", | ||||||
|                                             Kernel::KProcess::ProcessType::Userland) |                                             Kernel::KProcess::ProcessType::Userland) | ||||||
|                    .IsSuccess()); |                    .IsSuccess()); | ||||||
|         main_process->Open(); |  | ||||||
|         const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); |         const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); | ||||||
|         if (load_result != Loader::ResultStatus::Success) { |         if (load_result != Loader::ResultStatus::Success) { | ||||||
|             LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); |             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)); |                 static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); | ||||||
|         } |         } | ||||||
|         AddGlueRegistrationForProcess(*app_loader, *main_process); |         AddGlueRegistrationForProcess(*app_loader, *main_process); | ||||||
|         kernel.MakeCurrentProcess(main_process.get()); |         kernel.MakeCurrentProcess(main_process); | ||||||
|         kernel.InitializeCores(); |         kernel.InitializeCores(); | ||||||
| 
 | 
 | ||||||
|         // Initialize cheat engine
 |         // Initialize cheat engine
 | ||||||
| @ -340,8 +333,6 @@ struct System::Impl { | |||||||
|         kernel.Shutdown(); |         kernel.Shutdown(); | ||||||
|         memory.Reset(); |         memory.Reset(); | ||||||
|         applet_manager.ClearAll(); |         applet_manager.ClearAll(); | ||||||
|         // TODO: The main process should be freed based on KAutoObject ref counting.
 |  | ||||||
|         main_process.reset(); |  | ||||||
| 
 | 
 | ||||||
|         LOG_DEBUG(Core, "Shutdown OK"); |         LOG_DEBUG(Core, "Shutdown OK"); | ||||||
|     } |     } | ||||||
| @ -403,7 +394,6 @@ struct System::Impl { | |||||||
|     std::unique_ptr<Tegra::GPU> gpu_core; |     std::unique_ptr<Tegra::GPU> gpu_core; | ||||||
|     std::unique_ptr<Hardware::InterruptManager> interrupt_manager; |     std::unique_ptr<Hardware::InterruptManager> interrupt_manager; | ||||||
|     std::unique_ptr<Core::DeviceMemory> device_memory; |     std::unique_ptr<Core::DeviceMemory> device_memory; | ||||||
|     KProcessPtr main_process{nullptr, KProcessDeleter}; |  | ||||||
|     Core::Memory::Memory memory; |     Core::Memory::Memory memory; | ||||||
|     CpuManager cpu_manager; |     CpuManager cpu_manager; | ||||||
|     std::atomic_bool is_powered_on{}; |     std::atomic_bool is_powered_on{}; | ||||||
|  | |||||||
| @ -56,6 +56,7 @@ bool KHandleTable::Remove(Handle handle) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Close the object.
 |     // Close the object.
 | ||||||
|  |     kernel.UnregisterInUseObject(obj); | ||||||
|     obj->Close(); |     obj->Close(); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -434,11 +434,6 @@ void KProcess::PrepareForTermination() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void KProcess::Finalize() { | 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.
 |     // Finalize the handle table and close any open handles.
 | ||||||
|     handle_table.Finalize(); |     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.
 |     // Perform inherited finalization.
 | ||||||
|     KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); |     KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -91,12 +91,6 @@ struct KernelCore::Impl { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void Shutdown() { |     void Shutdown() { | ||||||
|         // Shutdown all processes.
 |  | ||||||
|         if (current_process) { |  | ||||||
|             current_process->Finalize(); |  | ||||||
|             current_process->Close(); |  | ||||||
|             current_process = nullptr; |  | ||||||
|         } |  | ||||||
|         process_list.clear(); |         process_list.clear(); | ||||||
| 
 | 
 | ||||||
|         // Close all open server ports.
 |         // 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 thead ID to use, 0-3 IDs represent core threads, >3 represent others
 | ||||||
|         next_host_thread_id = Core::Hardware::NUM_CPU_CORES; |         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
 |         // Track kernel objects that were not freed on shutdown
 | ||||||
|         { |         { | ||||||
|             std::lock_guard lk(registered_objects_lock); |             std::lock_guard lk(registered_objects_lock); | ||||||
| @ -714,9 +726,11 @@ struct KernelCore::Impl { | |||||||
|     std::unordered_set<KServerPort*> server_ports; |     std::unordered_set<KServerPort*> server_ports; | ||||||
|     std::unordered_set<KServerSession*> server_sessions; |     std::unordered_set<KServerSession*> server_sessions; | ||||||
|     std::unordered_set<KAutoObject*> registered_objects; |     std::unordered_set<KAutoObject*> registered_objects; | ||||||
|  |     std::unordered_set<KAutoObject*> registered_in_use_objects; | ||||||
|     std::mutex server_ports_lock; |     std::mutex server_ports_lock; | ||||||
|     std::mutex server_sessions_lock; |     std::mutex server_sessions_lock; | ||||||
|     std::mutex registered_objects_lock; |     std::mutex registered_objects_lock; | ||||||
|  |     std::mutex registered_in_use_objects_lock; | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | ||||||
|     std::vector<Kernel::PhysicalCore> cores; |     std::vector<Kernel::PhysicalCore> cores; | ||||||
| @ -928,6 +942,16 @@ void KernelCore::UnregisterKernelObject(KAutoObject* object) { | |||||||
|     impl->registered_objects.erase(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 { | bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const { | ||||||
|     return port != impl->named_ports.cend(); |     return port != impl->named_ports.cend(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -204,6 +204,14 @@ public: | |||||||
|     /// destroyed during the current emulation session.
 |     /// destroyed during the current emulation session.
 | ||||||
|     void UnregisterKernelObject(KAutoObject* object); |     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.
 |     /// Determines whether or not the given port is a valid named port.
 | ||||||
|     bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |     bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -427,11 +427,15 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha | |||||||
|         R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, |         R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, | ||||||
|                                                                          num_handles), |                                                                          num_handles), | ||||||
|                  ResultInvalidHandle); |                  ResultInvalidHandle); | ||||||
|  |         for (const auto& obj : objs) { | ||||||
|  |             kernel.RegisterInUseObject(obj); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Ensure handles are closed when we're done.
 |     // Ensure handles are closed when we're done.
 | ||||||
|     SCOPE_EXIT({ |     SCOPE_EXIT({ | ||||||
|         for (u64 i = 0; i < num_handles; ++i) { |         for (u64 i = 0; i < num_handles; ++i) { | ||||||
|  |             kernel.UnregisterInUseObject(objs[i]); | ||||||
|             objs[i]->Close(); |             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.
 |     // If we succeeded, persist a reference to the thread.
 | ||||||
|     thread->Open(); |     thread->Open(); | ||||||
|  |     system.Kernel().RegisterInUseObject(thread.GetPointerUnsafe()); | ||||||
| 
 | 
 | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| } | } | ||||||
| @ -1576,6 +1581,7 @@ static void ExitThread(Core::System& system) { | |||||||
|     auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); |     auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); | ||||||
|     system.GlobalSchedulerContext().RemoveThread(current_thread); |     system.GlobalSchedulerContext().RemoveThread(current_thread); | ||||||
|     current_thread->Exit(); |     current_thread->Exit(); | ||||||
|  |     system.Kernel().UnregisterInUseObject(current_thread); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ExitThread32(Core::System& system) { | static void ExitThread32(Core::System& system) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user