Browse Source
Merge pull request #6441 from bunnei/fix-session-handler
hle: kernel: KServerSession: Fix client disconnected.
pull/15/merge
bunnei
5 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with
21 additions and
17 deletions
-
src/core/hle/kernel/hle_ipc.cpp
-
src/core/hle/kernel/k_client_port.cpp
-
src/core/hle/kernel/k_server_session.h
-
src/core/hle/service/service.h
-
src/core/hle/service/sm/sm.cpp
|
|
|
@ -57,11 +57,11 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co |
|
|
|
} |
|
|
|
|
|
|
|
void SessionRequestHandler::ClientConnected(KServerSession* session) { |
|
|
|
session->SetSessionHandler(shared_from_this()); |
|
|
|
session->ClientConnected(shared_from_this()); |
|
|
|
} |
|
|
|
|
|
|
|
void SessionRequestHandler::ClientDisconnected(KServerSession* session) { |
|
|
|
session->SetSessionHandler(nullptr); |
|
|
|
session->ClientDisconnected(); |
|
|
|
} |
|
|
|
|
|
|
|
HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, |
|
|
|
|
|
|
|
@ -28,6 +28,9 @@ void KClientPort::Initialize(KPort* parent_port_, s32 max_sessions_, std::string |
|
|
|
void KClientPort::OnSessionFinalized() { |
|
|
|
KScopedSchedulerLock sl{kernel}; |
|
|
|
|
|
|
|
// This might happen if a session was improperly used with this port.
|
|
|
|
ASSERT_MSG(num_sessions > 0, "num_sessions is invalid"); |
|
|
|
|
|
|
|
const auto prev = num_sessions--; |
|
|
|
if (prev == max_sessions) { |
|
|
|
this->NotifyAvailable(); |
|
|
|
@ -66,7 +69,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out, |
|
|
|
// Update the session counts.
|
|
|
|
{ |
|
|
|
// Atomically increment the number of sessions.
|
|
|
|
s32 new_sessions; |
|
|
|
s32 new_sessions{}; |
|
|
|
{ |
|
|
|
const auto max = max_sessions; |
|
|
|
auto cur_sessions = num_sessions.load(std::memory_order_acquire); |
|
|
|
|
|
|
|
@ -62,15 +62,14 @@ public: |
|
|
|
|
|
|
|
void OnClientClosed(); |
|
|
|
|
|
|
|
/** |
|
|
|
* Sets the HLE handler for the session. This handler will be called to service IPC requests |
|
|
|
* instead of the regular IPC machinery. (The regular IPC machinery is currently not |
|
|
|
* implemented.) |
|
|
|
*/ |
|
|
|
void SetSessionHandler(SessionRequestHandlerPtr handler) { |
|
|
|
void ClientConnected(SessionRequestHandlerPtr handler) { |
|
|
|
manager->SetSessionHandler(std::move(handler)); |
|
|
|
} |
|
|
|
|
|
|
|
void ClientDisconnected() { |
|
|
|
manager = nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Handle a sync request from the emulated application. |
|
|
|
* |
|
|
|
|
|
|
|
@ -40,9 +40,11 @@ namespace SM { |
|
|
|
class ServiceManager; |
|
|
|
} |
|
|
|
|
|
|
|
static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters) |
|
|
|
/// Arbitrary default number of maximum connections to an HLE service. |
|
|
|
static const u32 DefaultMaxSessions = 0x10000; |
|
|
|
/// Default number of maximum connections to a server session. |
|
|
|
static constexpr u32 ServerSessionCountMax = 0x40; |
|
|
|
static_assert(ServerSessionCountMax == 0x40, |
|
|
|
"ServerSessionCountMax isn't 0x40 somehow, this assert is a reminder that this will " |
|
|
|
"break lots of things"); |
|
|
|
|
|
|
|
/** |
|
|
|
* This is an non-templated base of ServiceFramework to reduce code bloat and compilation times, it |
|
|
|
@ -178,7 +180,7 @@ protected: |
|
|
|
* connected to this service at the same time. |
|
|
|
*/ |
|
|
|
explicit ServiceFramework(Core::System& system_, const char* service_name_, |
|
|
|
u32 max_sessions_ = DefaultMaxSessions) |
|
|
|
u32 max_sessions_ = ServerSessionCountMax) |
|
|
|
: ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {} |
|
|
|
|
|
|
|
/// Registers handlers in the service. |
|
|
|
|
|
|
|
@ -164,18 +164,18 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext& |
|
|
|
R_UNLESS(session_reservation.Succeeded(), Kernel::ResultLimitReached); |
|
|
|
|
|
|
|
// Create a new session.
|
|
|
|
auto* session = Kernel::KSession::Create(kernel); |
|
|
|
session->Initialize(&port->GetClientPort(), std::move(name)); |
|
|
|
Kernel::KClientSession* session{}; |
|
|
|
port->GetClientPort().CreateSession(std::addressof(session)); |
|
|
|
|
|
|
|
// Commit the session reservation.
|
|
|
|
session_reservation.Commit(); |
|
|
|
|
|
|
|
// Enqueue the session with the named port.
|
|
|
|
port->EnqueueSession(&session->GetServerSession()); |
|
|
|
port->EnqueueSession(&session->GetParent()->GetServerSession()); |
|
|
|
|
|
|
|
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); |
|
|
|
|
|
|
|
return MakeResult(&session->GetClientSession()); |
|
|
|
return MakeResult(session); |
|
|
|
} |
|
|
|
|
|
|
|
void SM::RegisterService(Kernel::HLERequestContext& ctx) { |
|
|
|
|