kernel: more complete fix for KPort reference counting

This commit is contained in:
Liam 2022-10-30 20:58:20 -04:00
parent d8ff939edc
commit 4e9adae5da
2 changed files with 27 additions and 13 deletions

View file

@ -149,9 +149,10 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
return port_result.Code(); return port_result.Code();
} }
auto& port = port_result.Unwrap(); auto& port = port_result.Unwrap();
SCOPE_EXIT({ port->GetClientPort().Close(); }); SCOPE_EXIT({
port->GetClientPort().Close();
kernel.RegisterServerObject(&port->GetServerPort()); port->GetServerPort().Close();
});
// Create a new session. // Create a new session.
Kernel::KClientSession* session{}; Kernel::KClientSession* session{};

View file

@ -28,23 +28,36 @@ void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service, "called"); LOG_DEBUG(Service, "called");
auto& process = *ctx.GetThread().GetOwnerProcess();
auto& parent_session = *ctx.Session()->GetParent(); auto& parent_session = *ctx.Session()->GetParent();
auto& parent_port = parent_session.GetParent()->GetParent()->GetClientPort();
auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager(); auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager();
auto& session_handler = session_manager->SessionHandler();
// Create a session. // FIXME: this is duplicated from the SVC, it should just call it instead
Kernel::KClientSession* session{}; // once this is a proper process
const Result result = parent_port.CreateSession(std::addressof(session), session_manager);
if (result.IsError()) { // Reserve a new session from the process resource limit.
LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw); Kernel::KScopedResourceReservation session_reservation(&process,
IPC::ResponseBuilder rb{ctx, 2}; Kernel::LimitableResource::Sessions);
rb.Push(result); ASSERT(session_reservation.Succeeded());
}
// Create the session.
Kernel::KSession* session = Kernel::KSession::Create(system.Kernel());
ASSERT(session != nullptr);
// Initialize the session.
session->Initialize(nullptr, parent_session.GetName(), session_manager);
// Commit the session reservation.
session_reservation.Commit();
// Register the session.
session_handler.ClientConnected(&session->GetServerSession());
// We succeeded. // We succeeded.
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushMoveObjects(session); rb.PushMoveObjects(session->GetClientSession());
} }
void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) { void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {