Skip to content
Snippets Groups Projects
Commit a7f73d60 authored by bunnei's avatar bunnei
Browse files

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.
parent b44a5647
No related branches found
No related tags found
No related merge requests found
...@@ -59,6 +59,9 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co ...@@ -59,6 +59,9 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co
void SessionRequestHandler::ClientConnected(KServerSession* session) { void SessionRequestHandler::ClientConnected(KServerSession* session) {
session->ClientConnected(shared_from_this()); session->ClientConnected(shared_from_this());
// Ensure our server session is tracked globally.
kernel.RegisterServerObject(session);
} }
void SessionRequestHandler::ClientDisconnected(KServerSession* session) { void SessionRequestHandler::ClientDisconnected(KServerSession* session) {
......
...@@ -65,6 +65,9 @@ void KServerPort::Destroy() { ...@@ -65,6 +65,9 @@ void KServerPort::Destroy() {
// Release host emulation members. // Release host emulation members.
session_handler.reset(); 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 { bool KServerPort::IsSignaled() const {
......
...@@ -49,6 +49,9 @@ void KServerSession::Destroy() { ...@@ -49,6 +49,9 @@ void KServerSession::Destroy() {
// Release host emulation members. // Release host emulation members.
manager.reset(); manager.reset();
// Ensure that the global list tracking server objects does not hold on to a reference.
kernel.UnregisterServerObject(this);
} }
void KServerSession::OnClientClosed() { void KServerSession::OnClientClosed() {
......
...@@ -96,15 +96,15 @@ struct KernelCore::Impl { ...@@ -96,15 +96,15 @@ struct KernelCore::Impl {
process_list.clear(); process_list.clear();
// Close all open server ports. // Close all open server sessions and ports.
std::unordered_set<KServerPort*> server_ports_; std::unordered_set<KAutoObject*> server_objects_;
{ {
std::scoped_lock lk{server_ports_lock}; std::scoped_lock lk(server_objects_lock);
server_ports_ = server_ports; server_objects_ = server_objects;
server_ports.clear(); server_objects.clear();
} }
for (auto* server_port : server_ports_) { for (auto* server_object : server_objects_) {
server_port->Close(); server_object->Close();
} }
// Ensures all service threads gracefully shutdown. // Ensures all service threads gracefully shutdown.
...@@ -659,13 +659,20 @@ struct KernelCore::Impl { ...@@ -659,13 +659,20 @@ struct KernelCore::Impl {
} }
KClientPort* port = &search->second(system.ServiceManager(), system); KClientPort* port = &search->second(system.ServiceManager(), system);
{ RegisterServerObject(&port->GetParent()->GetServerPort());
std::scoped_lock lk{server_ports_lock};
server_ports.insert(&port->GetParent()->GetServerPort());
}
return port; 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<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel, std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel,
const std::string& name) { const std::string& name) {
auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, 1, name); auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, 1, name);
...@@ -693,7 +700,7 @@ struct KernelCore::Impl { ...@@ -693,7 +700,7 @@ struct KernelCore::Impl {
service_threads_manager.QueueWork([this]() { service_threads.clear(); }); 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_objects_lock;
std::mutex registered_in_use_objects_lock; std::mutex registered_in_use_objects_lock;
...@@ -723,7 +730,7 @@ struct KernelCore::Impl { ...@@ -723,7 +730,7 @@ struct KernelCore::Impl {
/// the ConnectToPort SVC. /// the ConnectToPort SVC.
std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory; std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
NamedPortTable named_ports; NamedPortTable named_ports;
std::unordered_set<KServerPort*> server_ports; std::unordered_set<KAutoObject*> server_objects;
std::unordered_set<KAutoObject*> registered_objects; std::unordered_set<KAutoObject*> registered_objects;
std::unordered_set<KAutoObject*> registered_in_use_objects; std::unordered_set<KAutoObject*> registered_in_use_objects;
...@@ -928,6 +935,14 @@ KClientPort* KernelCore::CreateNamedServicePort(std::string name) { ...@@ -928,6 +935,14 @@ KClientPort* KernelCore::CreateNamedServicePort(std::string name) {
return impl->CreateNamedServicePort(std::move(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) { void KernelCore::RegisterKernelObject(KAutoObject* object) {
std::scoped_lock lk{impl->registered_objects_lock}; std::scoped_lock lk{impl->registered_objects_lock};
impl->registered_objects.insert(object); impl->registered_objects.insert(object);
......
...@@ -195,6 +195,14 @@ public: ...@@ -195,6 +195,14 @@ public:
/// Opens a port to a service previously registered with RegisterNamedService. /// Opens a port to a service previously registered with RegisterNamedService.
KClientPort* CreateNamedServicePort(std::string name); 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 /// Registers all kernel objects with the global emulation state, this is purely for tracking
/// leaks after emulation has been shutdown. /// leaks after emulation has been shutdown.
void RegisterKernelObject(KAutoObject* object); void RegisterKernelObject(KAutoObject* object);
......
...@@ -153,6 +153,7 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& ...@@ -153,6 +153,7 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
auto& port = port_result.Unwrap(); auto& port = port_result.Unwrap();
SCOPE_EXIT({ port->GetClientPort().Close(); }); SCOPE_EXIT({ port->GetClientPort().Close(); });
kernel.RegisterServerObject(&port->GetServerPort());
// Create a new session. // Create a new session.
Kernel::KClientSession* session{}; Kernel::KClientSession* session{};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment