mirror of
https://git.h3cjp.net/H3cJP/citra.git
synced 2024-11-24 14:32:47 +00:00
Fix Service object leak on emulation stop
Services created with the ServiceFramework base class install themselves as HleHandlers with an owning shared_ptr in the ServerPort ServiceFrameworkBase::port member variable, creating a cyclic ownership between ServiceFrameworkBase and the ServerPort, preventing deletion of the service objects. Fix that by removing the ServiceFrameworkBase::port member because that was only used to detect multiple attempts at installing a port. Instead store a flag if the port was already installed to achieve the same functionality.
This commit is contained in:
parent
700075beb6
commit
27a9cc2e63
|
@ -97,29 +97,33 @@ ServiceFrameworkBase::ServiceFrameworkBase(const char* service_name, u32 max_ses
|
||||||
ServiceFrameworkBase::~ServiceFrameworkBase() = default;
|
ServiceFrameworkBase::~ServiceFrameworkBase() = default;
|
||||||
|
|
||||||
void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
|
void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager) {
|
||||||
ASSERT(port == nullptr);
|
ASSERT(!port_installed);
|
||||||
port = service_manager.RegisterService(service_name, max_sessions).Unwrap();
|
|
||||||
|
auto port = service_manager.RegisterService(service_name, max_sessions).Unwrap();
|
||||||
port->SetHleHandler(shared_from_this());
|
port->SetHleHandler(shared_from_this());
|
||||||
|
port_installed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceFrameworkBase::InstallAsNamedPort() {
|
void ServiceFrameworkBase::InstallAsNamedPort() {
|
||||||
ASSERT(port == nullptr);
|
ASSERT(!port_installed);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
auto& kernel = Core::System::GetInstance().Kernel();
|
||||||
auto [server_port, client_port] =
|
auto [server_port, client_port] =
|
||||||
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
|
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
|
||||||
server_port->SetHleHandler(shared_from_this());
|
server_port->SetHleHandler(shared_from_this());
|
||||||
kernel.AddNamedPort(service_name, std::move(client_port));
|
kernel.AddNamedPort(service_name, std::move(client_port));
|
||||||
|
port_installed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Kernel::SharedPtr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {
|
Kernel::SharedPtr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {
|
||||||
ASSERT(port == nullptr);
|
ASSERT(!port_installed);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
auto& kernel = Core::System::GetInstance().Kernel();
|
||||||
auto [server_port, client_port] =
|
auto [server_port, client_port] =
|
||||||
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
|
Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
|
||||||
port = MakeResult(std::move(server_port)).Unwrap();
|
auto port = MakeResult(std::move(server_port)).Unwrap();
|
||||||
port->SetHleHandler(shared_from_this());
|
port->SetHleHandler(shared_from_this());
|
||||||
|
port_installed = true;
|
||||||
return client_port;
|
return client_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,11 +96,9 @@ private:
|
||||||
/// Maximum number of concurrent sessions that this service can handle.
|
/// Maximum number of concurrent sessions that this service can handle.
|
||||||
u32 max_sessions;
|
u32 max_sessions;
|
||||||
|
|
||||||
/**
|
/// Flag to store if a port was already create/installed to detect multiple install attempts,
|
||||||
* Port where incoming connections will be received. Only created when InstallAsService() or
|
/// which is not supported.
|
||||||
* InstallAsNamedPort() are called.
|
bool port_installed = false;
|
||||||
*/
|
|
||||||
Kernel::SharedPtr<Kernel::ServerPort> port;
|
|
||||||
|
|
||||||
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
|
/// Function used to safely up-cast pointers to the derived class before invoking a handler.
|
||||||
InvokerFn* handler_invoker;
|
InvokerFn* handler_invoker;
|
||||||
|
|
Loading…
Reference in a new issue