From a7f73d606f596ab73cf794a76c06cd955033cada Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 6 Apr 2022 17:44:06 -0700 Subject: hle: kernel: Unify and integrate reference tracking for KServerPort/KServerSession. - These are not managed elsewhere, and need to be tracked and closed on emulation shutdown. --- src/core/hle/kernel/hle_ipc.cpp | 3 +++ src/core/hle/kernel/k_server_port.cpp | 3 +++ src/core/hle/kernel/k_server_session.cpp | 3 +++ src/core/hle/kernel/kernel.cpp | 41 ++++++++++++++++++++++---------- src/core/hle/kernel/kernel.h | 8 +++++++ src/core/hle/service/sm/sm.cpp | 1 + 6 files changed, 46 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 7692d02e1..5828ac923 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -59,6 +59,9 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co void SessionRequestHandler::ClientConnected(KServerSession* session) { session->ClientConnected(shared_from_this()); + + // Ensure our server session is tracked globally. + kernel.RegisterServerObject(session); } void SessionRequestHandler::ClientDisconnected(KServerSession* session) { diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index 6922a07cb..e66c0c992 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp @@ -65,6 +65,9 @@ void KServerPort::Destroy() { // Release host emulation members. session_handler.reset(); + + // Ensure that the global list tracking server objects does not hold on to a reference. + kernel.UnregisterServerObject(this); } bool KServerPort::IsSignaled() const { diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 30c56ff29..7ac2ef254 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -49,6 +49,9 @@ void KServerSession::Destroy() { // Release host emulation members. manager.reset(); + + // Ensure that the global list tracking server objects does not hold on to a reference. + kernel.UnregisterServerObject(this); } void KServerSession::OnClientClosed() { diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 134a0b8e9..cc6ee0eae 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -96,15 +96,15 @@ struct KernelCore::Impl { process_list.clear(); - // Close all open server ports. - std::unordered_set server_ports_; + // Close all open server sessions and ports. + std::unordered_set server_objects_; { - std::scoped_lock lk{server_ports_lock}; - server_ports_ = server_ports; - server_ports.clear(); + std::scoped_lock lk(server_objects_lock); + server_objects_ = server_objects; + server_objects.clear(); } - for (auto* server_port : server_ports_) { - server_port->Close(); + for (auto* server_object : server_objects_) { + server_object->Close(); } // Ensures all service threads gracefully shutdown. @@ -659,13 +659,20 @@ struct KernelCore::Impl { } KClientPort* port = &search->second(system.ServiceManager(), system); - { - std::scoped_lock lk{server_ports_lock}; - server_ports.insert(&port->GetParent()->GetServerPort()); - } + RegisterServerObject(&port->GetParent()->GetServerPort()); return port; } + void RegisterServerObject(KAutoObject* server_object) { + std::scoped_lock lk(server_objects_lock); + server_objects.insert(server_object); + } + + void UnregisterServerObject(KAutoObject* server_object) { + std::scoped_lock lk(server_objects_lock); + server_objects.erase(server_object); + } + std::weak_ptr CreateServiceThread(KernelCore& kernel, const std::string& name) { auto service_thread = std::make_shared(kernel, 1, name); @@ -693,7 +700,7 @@ struct KernelCore::Impl { service_threads_manager.QueueWork([this]() { service_threads.clear(); }); } - std::mutex server_ports_lock; + std::mutex server_objects_lock; std::mutex registered_objects_lock; std::mutex registered_in_use_objects_lock; @@ -723,7 +730,7 @@ struct KernelCore::Impl { /// the ConnectToPort SVC. std::unordered_map service_interface_factory; NamedPortTable named_ports; - std::unordered_set server_ports; + std::unordered_set server_objects; std::unordered_set registered_objects; std::unordered_set registered_in_use_objects; @@ -928,6 +935,14 @@ KClientPort* KernelCore::CreateNamedServicePort(std::string name) { return impl->CreateNamedServicePort(std::move(name)); } +void KernelCore::RegisterServerObject(KAutoObject* server_object) { + impl->RegisterServerObject(server_object); +} + +void KernelCore::UnregisterServerObject(KAutoObject* server_object) { + impl->UnregisterServerObject(server_object); +} + void KernelCore::RegisterKernelObject(KAutoObject* object) { std::scoped_lock lk{impl->registered_objects_lock}; impl->registered_objects.insert(object); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 24e26fa44..d709c368b 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -195,6 +195,14 @@ public: /// Opens a port to a service previously registered with RegisterNamedService. KClientPort* CreateNamedServicePort(std::string name); + /// Registers a server session or port with the gobal emulation state, to be freed on shutdown. + /// This is necessary because we do not emulate processes for HLE sessions and ports. + void RegisterServerObject(KAutoObject* server_object); + + /// Unregisters a server session or port previously registered with RegisterServerSession when + /// it was destroyed during the current emulation session. + void UnregisterServerObject(KAutoObject* server_object); + /// Registers all kernel objects with the global emulation state, this is purely for tracking /// leaks after emulation has been shutdown. void RegisterKernelObject(KAutoObject* object); diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 2ac6dc596..13f5e08ec 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -153,6 +153,7 @@ ResultVal SM::GetServiceImpl(Kernel::HLERequestContext& auto& port = port_result.Unwrap(); SCOPE_EXIT({ port->GetClientPort().Close(); }); + kernel.RegisterServerObject(&port->GetServerPort()); // Create a new session. Kernel::KClientSession* session{}; -- cgit v1.2.3