summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/k_server_session.cpp31
1 files changed, 24 insertions, 7 deletions
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index dd62706a8..5c3c13ce6 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -8,6 +8,7 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/scope_exit.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
@@ -119,11 +120,20 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor
context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
+ // In the event that something fails here, stub a result to prevent the game from crashing.
+ // This is a work-around in the event that somehow we process a service request after the
+ // session has been closed by the game. This has been observed to happen rarely in Pokemon
+ // Sword/Shield and is likely a result of us using host threads/scheduling for services.
+ // TODO(bunnei): Find a better solution here.
+ auto error_guard = SCOPE_GUARD({ CompleteSyncRequest(*context); });
+
// Ensure we have a session request handler
if (manager->HasSessionRequestHandler(*context)) {
if (auto strong_ptr = manager->GetServiceThread().lock()) {
strong_ptr->QueueSyncRequest(*parent, std::move(context));
- return ResultSuccess;
+
+ // We succeeded.
+ error_guard.Cancel();
} else {
ASSERT_MSG(false, "strong_ptr is nullptr!");
}
@@ -136,13 +146,20 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor
ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) {
ResultCode result = ResultSuccess;
+
// If the session has been converted to a domain, handle the domain request
- if (IsDomain() && context.HasDomainMessageHeader()) {
- result = HandleDomainSyncRequest(context);
- // If there is no domain header, the regular session handler is used
- } else if (manager->HasSessionHandler()) {
- // If this ServerSession has an associated HLE handler, forward the request to it.
- result = manager->SessionHandler().HandleSyncRequest(*this, context);
+ if (manager->HasSessionRequestHandler(context)) {
+ if (IsDomain() && context.HasDomainMessageHeader()) {
+ result = HandleDomainSyncRequest(context);
+ // If there is no domain header, the regular session handler is used
+ } else if (manager->HasSessionHandler()) {
+ // If this ServerSession has an associated HLE handler, forward the request to it.
+ result = manager->SessionHandler().HandleSyncRequest(*this, context);
+ }
+ } else {
+ ASSERT_MSG(false, "Session handler is invalid, stubbing response!");
+ IPC::ResponseBuilder rb(context, 2);
+ rb.Push(ResultSuccess);
}
if (convert_to_domain) {