diff options
| author | 2022-04-12 14:01:40 -0700 | |
|---|---|---|
| committer | 2022-04-12 14:01:40 -0700 | |
| commit | ca2accfb259b948431ec174ead432778f3c86f67 (patch) | |
| tree | f3729b67e09270683a948f48169185c2360cc4af | |
| parent | Merge pull request #8178 from tech-ticks/skyline-icache-fix (diff) | |
| parent | hle: kernel: Unify and integrate reference tracking for KServerPort/KServerSe... (diff) | |
| download | yuzu-ca2accfb259b948431ec174ead432778f3c86f67.tar.gz yuzu-ca2accfb259b948431ec174ead432778f3c86f67.tar.xz yuzu-ca2accfb259b948431ec174ead432778f3c86f67.zip | |
Merge pull request #8165 from bunnei/ensure-session-port-cleanup
Kernel: Track open references to KServerPort and KServerSession.
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_auto_object.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_port.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_server_session.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 41 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 8 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.h | 2 |
8 files changed, 53 insertions, 25 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index b547a3463..5828ac923 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -51,7 +51,7 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co | |||
| 51 | LOG_CRITICAL(IPC, "object_id {} is too big!", object_id); | 51 | LOG_CRITICAL(IPC, "object_id {} is too big!", object_id); |
| 52 | return false; | 52 | return false; |
| 53 | } | 53 | } |
| 54 | return DomainHandler(object_id - 1).lock() != nullptr; | 54 | return !DomainHandler(object_id - 1).expired(); |
| 55 | } else { | 55 | } else { |
| 56 | return session_handler != nullptr; | 56 | return session_handler != nullptr; |
| 57 | } | 57 | } |
| @@ -59,6 +59,9 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co | |||
| 59 | 59 | ||
| 60 | void SessionRequestHandler::ClientConnected(KServerSession* session) { | 60 | void SessionRequestHandler::ClientConnected(KServerSession* session) { |
| 61 | session->ClientConnected(shared_from_this()); | 61 | session->ClientConnected(shared_from_this()); |
| 62 | |||
| 63 | // Ensure our server session is tracked globally. | ||
| 64 | kernel.RegisterServerObject(session); | ||
| 62 | } | 65 | } |
| 63 | 66 | ||
| 64 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { | 67 | void SessionRequestHandler::ClientDisconnected(KServerSession* session) { |
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index abdb8ae7c..423e8d8f5 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h | |||
| @@ -89,9 +89,7 @@ public: | |||
| 89 | explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) { | 89 | explicit KAutoObject(KernelCore& kernel_) : kernel(kernel_) { |
| 90 | RegisterWithKernel(); | 90 | RegisterWithKernel(); |
| 91 | } | 91 | } |
| 92 | virtual ~KAutoObject() { | 92 | virtual ~KAutoObject() = default; |
| 93 | UnregisterWithKernel(); | ||
| 94 | } | ||
| 95 | 93 | ||
| 96 | static KAutoObject* Create(KAutoObject* ptr); | 94 | static KAutoObject* Create(KAutoObject* ptr); |
| 97 | 95 | ||
| @@ -168,6 +166,7 @@ public: | |||
| 168 | // If ref count hits zero, destroy the object. | 166 | // If ref count hits zero, destroy the object. |
| 169 | if (cur_ref_count - 1 == 0) { | 167 | if (cur_ref_count - 1 == 0) { |
| 170 | this->Destroy(); | 168 | this->Destroy(); |
| 169 | this->UnregisterWithKernel(); | ||
| 171 | } | 170 | } |
| 172 | } | 171 | } |
| 173 | 172 | ||
diff --git a/src/core/hle/kernel/k_server_port.cpp b/src/core/hle/kernel/k_server_port.cpp index 433fc98e1..e66c0c992 100644 --- a/src/core/hle/kernel/k_server_port.cpp +++ b/src/core/hle/kernel/k_server_port.cpp | |||
| @@ -62,6 +62,12 @@ void KServerPort::Destroy() { | |||
| 62 | 62 | ||
| 63 | // Close our reference to our parent. | 63 | // Close our reference to our parent. |
| 64 | parent->Close(); | 64 | parent->Close(); |
| 65 | |||
| 66 | // Release host emulation members. | ||
| 67 | session_handler.reset(); | ||
| 68 | |||
| 69 | // Ensure that the global list tracking server objects does not hold on to a reference. | ||
| 70 | kernel.UnregisterServerObject(this); | ||
| 65 | } | 71 | } |
| 66 | 72 | ||
| 67 | bool KServerPort::IsSignaled() const { | 73 | 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() { | |||
| 49 | 49 | ||
| 50 | // Release host emulation members. | 50 | // Release host emulation members. |
| 51 | manager.reset(); | 51 | manager.reset(); |
| 52 | |||
| 53 | // Ensure that the global list tracking server objects does not hold on to a reference. | ||
| 54 | kernel.UnregisterServerObject(this); | ||
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | void KServerSession::OnClientClosed() { | 57 | void KServerSession::OnClientClosed() { |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 481a0d7cb..d840d44e6 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -96,15 +96,15 @@ struct KernelCore::Impl { | |||
| 96 | 96 | ||
| 97 | process_list.clear(); | 97 | process_list.clear(); |
| 98 | 98 | ||
| 99 | // Close all open server ports. | 99 | // Close all open server sessions and ports. |
| 100 | std::unordered_set<KServerPort*> server_ports_; | 100 | std::unordered_set<KAutoObject*> server_objects_; |
| 101 | { | 101 | { |
| 102 | std::scoped_lock lk{server_ports_lock}; | 102 | std::scoped_lock lk(server_objects_lock); |
| 103 | server_ports_ = server_ports; | 103 | server_objects_ = server_objects; |
| 104 | server_ports.clear(); | 104 | server_objects.clear(); |
| 105 | } | 105 | } |
| 106 | for (auto* server_port : server_ports_) { | 106 | for (auto* server_object : server_objects_) { |
| 107 | server_port->Close(); | 107 | server_object->Close(); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | // Ensures all service threads gracefully shutdown. | 110 | // Ensures all service threads gracefully shutdown. |
| @@ -659,13 +659,20 @@ struct KernelCore::Impl { | |||
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | KClientPort* port = &search->second(system.ServiceManager(), system); | 661 | KClientPort* port = &search->second(system.ServiceManager(), system); |
| 662 | { | 662 | RegisterServerObject(&port->GetParent()->GetServerPort()); |
| 663 | std::scoped_lock lk{server_ports_lock}; | ||
| 664 | server_ports.insert(&port->GetParent()->GetServerPort()); | ||
| 665 | } | ||
| 666 | return port; | 663 | return port; |
| 667 | } | 664 | } |
| 668 | 665 | ||
| 666 | void RegisterServerObject(KAutoObject* server_object) { | ||
| 667 | std::scoped_lock lk(server_objects_lock); | ||
| 668 | server_objects.insert(server_object); | ||
| 669 | } | ||
| 670 | |||
| 671 | void UnregisterServerObject(KAutoObject* server_object) { | ||
| 672 | std::scoped_lock lk(server_objects_lock); | ||
| 673 | server_objects.erase(server_object); | ||
| 674 | } | ||
| 675 | |||
| 669 | std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel, | 676 | std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel, |
| 670 | const std::string& name) { | 677 | const std::string& name) { |
| 671 | auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, 1, name); | 678 | auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, 1, name); |
| @@ -693,7 +700,7 @@ struct KernelCore::Impl { | |||
| 693 | service_threads_manager.QueueWork([this]() { service_threads.clear(); }); | 700 | service_threads_manager.QueueWork([this]() { service_threads.clear(); }); |
| 694 | } | 701 | } |
| 695 | 702 | ||
| 696 | std::mutex server_ports_lock; | 703 | std::mutex server_objects_lock; |
| 697 | std::mutex registered_objects_lock; | 704 | std::mutex registered_objects_lock; |
| 698 | std::mutex registered_in_use_objects_lock; | 705 | std::mutex registered_in_use_objects_lock; |
| 699 | 706 | ||
| @@ -723,7 +730,7 @@ struct KernelCore::Impl { | |||
| 723 | /// the ConnectToPort SVC. | 730 | /// the ConnectToPort SVC. |
| 724 | std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; | 731 | std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; |
| 725 | NamedPortTable named_ports; | 732 | NamedPortTable named_ports; |
| 726 | std::unordered_set<KServerPort*> server_ports; | 733 | std::unordered_set<KAutoObject*> server_objects; |
| 727 | std::unordered_set<KAutoObject*> registered_objects; | 734 | std::unordered_set<KAutoObject*> registered_objects; |
| 728 | std::unordered_set<KAutoObject*> registered_in_use_objects; | 735 | std::unordered_set<KAutoObject*> registered_in_use_objects; |
| 729 | 736 | ||
| @@ -928,6 +935,14 @@ KClientPort* KernelCore::CreateNamedServicePort(std::string name) { | |||
| 928 | return impl->CreateNamedServicePort(std::move(name)); | 935 | return impl->CreateNamedServicePort(std::move(name)); |
| 929 | } | 936 | } |
| 930 | 937 | ||
| 938 | void KernelCore::RegisterServerObject(KAutoObject* server_object) { | ||
| 939 | impl->RegisterServerObject(server_object); | ||
| 940 | } | ||
| 941 | |||
| 942 | void KernelCore::UnregisterServerObject(KAutoObject* server_object) { | ||
| 943 | impl->UnregisterServerObject(server_object); | ||
| 944 | } | ||
| 945 | |||
| 931 | void KernelCore::RegisterKernelObject(KAutoObject* object) { | 946 | void KernelCore::RegisterKernelObject(KAutoObject* object) { |
| 932 | std::scoped_lock lk{impl->registered_objects_lock}; | 947 | std::scoped_lock lk{impl->registered_objects_lock}; |
| 933 | impl->registered_objects.insert(object); | 948 | 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: | |||
| 195 | /// Opens a port to a service previously registered with RegisterNamedService. | 195 | /// Opens a port to a service previously registered with RegisterNamedService. |
| 196 | KClientPort* CreateNamedServicePort(std::string name); | 196 | KClientPort* CreateNamedServicePort(std::string name); |
| 197 | 197 | ||
| 198 | /// Registers a server session or port with the gobal emulation state, to be freed on shutdown. | ||
| 199 | /// This is necessary because we do not emulate processes for HLE sessions and ports. | ||
| 200 | void RegisterServerObject(KAutoObject* server_object); | ||
| 201 | |||
| 202 | /// Unregisters a server session or port previously registered with RegisterServerSession when | ||
| 203 | /// it was destroyed during the current emulation session. | ||
| 204 | void UnregisterServerObject(KAutoObject* server_object); | ||
| 205 | |||
| 198 | /// Registers all kernel objects with the global emulation state, this is purely for tracking | 206 | /// Registers all kernel objects with the global emulation state, this is purely for tracking |
| 199 | /// leaks after emulation has been shutdown. | 207 | /// leaks after emulation has been shutdown. |
| 200 | void RegisterKernelObject(KAutoObject* object); | 208 | void RegisterKernelObject(KAutoObject* object); |
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 97f895852..13f5e08ec 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -153,7 +153,7 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& | |||
| 153 | auto& port = port_result.Unwrap(); | 153 | auto& port = port_result.Unwrap(); |
| 154 | SCOPE_EXIT({ port->GetClientPort().Close(); }); | 154 | SCOPE_EXIT({ port->GetClientPort().Close(); }); |
| 155 | 155 | ||
| 156 | server_ports.emplace_back(&port->GetServerPort()); | 156 | kernel.RegisterServerObject(&port->GetServerPort()); |
| 157 | 157 | ||
| 158 | // Create a new session. | 158 | // Create a new session. |
| 159 | Kernel::KClientSession* session{}; | 159 | Kernel::KClientSession* session{}; |
| @@ -224,10 +224,6 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_) | |||
| 224 | }); | 224 | }); |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | SM::~SM() { | 227 | SM::~SM() = default; |
| 228 | for (auto& server_port : server_ports) { | ||
| 229 | server_port->Close(); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | 228 | ||
| 233 | } // namespace Service::SM | 229 | } // namespace Service::SM |
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h index 021eb51b4..f3ff7b27e 100644 --- a/src/core/hle/service/sm/sm.h +++ b/src/core/hle/service/sm/sm.h | |||
| @@ -22,7 +22,6 @@ class KClientPort; | |||
| 22 | class KClientSession; | 22 | class KClientSession; |
| 23 | class KernelCore; | 23 | class KernelCore; |
| 24 | class KPort; | 24 | class KPort; |
| 25 | class KServerPort; | ||
| 26 | class SessionRequestHandler; | 25 | class SessionRequestHandler; |
| 27 | } // namespace Kernel | 26 | } // namespace Kernel |
| 28 | 27 | ||
| @@ -48,7 +47,6 @@ private: | |||
| 48 | ServiceManager& service_manager; | 47 | ServiceManager& service_manager; |
| 49 | bool is_initialized{}; | 48 | bool is_initialized{}; |
| 50 | Kernel::KernelCore& kernel; | 49 | Kernel::KernelCore& kernel; |
| 51 | std::vector<Kernel::KServerPort*> server_ports; | ||
| 52 | }; | 50 | }; |
| 53 | 51 | ||
| 54 | class ServiceManager { | 52 | class ServiceManager { |