Kernel/Sessions: Wake up any threads waiting on a ServerSession when its client is closed

The error code 0xC920181A will be returned by svcReplyAndReceive when the wakeup callback runs.
This lets LLE services be properly notified of clients closing the connection so they can end their handler threads instead of letting them linger indefinitely, taking up connection slots in their parent port.
This commit is contained in:
Subv 2017-11-06 23:07:08 -05:00
parent d55a13c35d
commit 06a2e0b591
2 changed files with 13 additions and 4 deletions

View file

@ -26,9 +26,6 @@ ClientSession::~ClientSession() {
if (hle_handler) if (hle_handler)
hle_handler->ClientDisconnected(server); hle_handler->ClientDisconnected(server);
// TODO(Subv): Force a wake up of all the ServerSession's waiting threads and set
// their WaitSynchronization result to 0xC920181A.
// Clean up the list of client threads with pending requests, they are unneeded now that the // Clean up the list of client threads with pending requests, they are unneeded now that the
// client endpoint is closed. // client endpoint is closed.
server->pending_requesting_threads.clear(); server->pending_requesting_threads.clear();
@ -36,6 +33,13 @@ ClientSession::~ClientSession() {
} }
parent->client = nullptr; parent->client = nullptr;
if (server) {
// Notify any threads waiting on the ServerSession that the endpoint has been closed. Note
// that this call has to happen after `Session::client` has been set to nullptr to let the
// ServerSession know that the client endpoint has been closed.
server->WakeupAllWaitingThreads();
}
} }
ResultCode ClientSession::SendSyncRequest(SharedPtr<Thread> thread) { ResultCode ClientSession::SendSyncRequest(SharedPtr<Thread> thread) {

View file

@ -47,8 +47,13 @@ bool ServerSession::ShouldWait(Thread* thread) const {
void ServerSession::Acquire(Thread* thread) { void ServerSession::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
// If the client endpoint was closed, don't do anything. This ServerSession is now useless and
// will linger until its last handle is closed by the running application.
if (parent->client == nullptr)
return;
// We are now handling a request, pop it from the stack. // We are now handling a request, pop it from the stack.
// TODO(Subv): What happens if the client endpoint is closed before any requests are made?
ASSERT(!pending_requesting_threads.empty()); ASSERT(!pending_requesting_threads.empty());
currently_handling = pending_requesting_threads.back(); currently_handling = pending_requesting_threads.back();
pending_requesting_threads.pop_back(); pending_requesting_threads.pop_back();