mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-03 16:39:01 -06:00 
			
		
		
		
	hle: kernel: KServerSession: Work-around scenario where session is closed too early.
This commit is contained in:
		@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user