From 670e207c5727bf1fdf923d5bb9c0c4ce32d23462 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 1 Nov 2018 21:27:01 -0700 Subject: [PATCH] Core: Wait for background CPU load on exit. This prevents crashes when exiting a game while loading is still in progress. See #11516. --- Core/Loaders.cpp | 4 ++++ Core/PSPLoaders.cpp | 16 ++++++++++++++++ Core/System.cpp | 14 ++++++++++++++ Core/System.h | 6 ++++++ UI/EmuScreen.cpp | 2 +- 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index ace145457d..c901a1245a 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -258,6 +258,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { } else if (ebootType == IdentifiedFileType::PSP_PS1_PBP) { *error_string = "PS1 EBOOTs are not supported by PPSSPP."; + coreState = CORE_ERROR; return false; } std::string path = fileLoader->Path(); @@ -269,6 +270,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { return Load_PSP_ELF_PBP(fileLoader, error_string); } else { *error_string = "No EBOOT.PBP, misidentified game"; + coreState = CORE_ERROR; return false; } } @@ -347,5 +349,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { *error_string = "Failed to identify file"; break; } + + coreState = CORE_ERROR; return false; } diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 8ff92b6e29..697a1240a9 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -247,6 +247,7 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) { } else { *error_string = "A PSP game couldn't be found on the disc."; } + coreState = CORE_ERROR; return false; } @@ -257,6 +258,10 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) { std::thread th([bootpath] { setCurrentThreadName("ExecLoader"); + PSP_LoadingLock guard; + if (coreState != CORE_POWERUP) + return; + PSP_SetLoading("Loading executable..."); // TODO: We can't use the initial error_string pointer. bool success = __KernelLoadExec(bootpath.c_str(), 0, &PSP_CoreParameter().errorString); @@ -327,6 +332,7 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { // If root is not a subpath of path, we can't boot the game. if (!startsWith(pathNorm, rootNorm)) { *error_string = "Cannot boot ELF located outside mountRoot."; + coreState = CORE_ERROR; return false; } @@ -374,6 +380,11 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) { // End of temporary code std::thread th([finalName] { + setCurrentThreadName("ExecLoader"); + PSP_LoadingLock guard; + if (coreState != CORE_POWERUP) + return; + bool success = __KernelLoadExec(finalName.c_str(), 0, &PSP_CoreParameter().errorString); if (success && coreState == CORE_POWERUP) { coreState = PSP_CoreParameter().startBreak ? CORE_STEPPING : CORE_RUNNING; @@ -392,6 +403,11 @@ bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) { pspFileSystem.Mount("disc0:", umd); std::thread th([] { + setCurrentThreadName("ExecLoader"); + PSP_LoadingLock guard; + if (coreState != CORE_POWERUP) + return; + bool success = __KernelLoadGEDump("disc0:/data.ppdmp", &PSP_CoreParameter().errorString); if (success && coreState == CORE_POWERUP) { coreState = PSP_CoreParameter().startBreak ? CORE_STEPPING : CORE_RUNNING; diff --git a/Core/System.cpp b/Core/System.cpp index 33accc49bb..67a4e6fd85 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -82,6 +82,9 @@ ParamSFOData g_paramSFO; static GlobalUIState globalUIState; static CoreParameter coreParameter; static FileLoader *loadedFile; +// For background loading thread. +static std::mutex loadingLock; +// For loadingReason updates. static std::mutex loadingReasonLock; static std::string loadingReason; @@ -255,7 +258,18 @@ void CPU_Init() { } } +PSP_LoadingLock::PSP_LoadingLock() { + loadingLock.lock(); +} + +PSP_LoadingLock::~PSP_LoadingLock() { + loadingLock.unlock(); +} + void CPU_Shutdown() { + // Since we load on a background thread, wait for startup to complete. + PSP_LoadingLock lock; + if (g_Config.bAutoSaveSymbolMap) { host->SaveSymbolMap(); } diff --git a/Core/System.h b/Core/System.h index c46b54fd13..43be1e55eb 100644 --- a/Core/System.h +++ b/Core/System.h @@ -79,6 +79,12 @@ void PSP_RunLoopFor(int cycles); void PSP_SetLoading(const std::string &reason); std::string PSP_GetLoading(); +// Used to wait for background loading thread. +struct PSP_LoadingLock { + PSP_LoadingLock(); + ~PSP_LoadingLock(); +}; + // Call before PSP_BeginHostFrame() in order to not miss any GPU stats. void Core_UpdateDebugStats(bool collectStats); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 023419fc66..b638661074 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -334,7 +334,7 @@ void EmuScreen::bootComplete() { } EmuScreen::~EmuScreen() { - if (!invalid_) { + if (!invalid_ || bootPending_) { // If we were invalid, it would already be shutdown. PSP_Shutdown(); }