Skip to content

Commit

Permalink
Dialog: Try to recover on double init, report.
Browse files Browse the repository at this point in the history
This shouldn't be happening, but is - see #14864.
Let's report the situation and try to avoid a complete crash.
  • Loading branch information
unknownbrackets committed Sep 16, 2021
1 parent 433daf1 commit 570d84f
Showing 1 changed file with 33 additions and 10 deletions.
43 changes: 33 additions & 10 deletions Core/HLE/sceUtility.cpp
Expand Up @@ -136,29 +136,43 @@ static int oldStatus = -1;
static std::map<int, u32> currentlyLoadedModules;
static int volatileUnlockEvent = -1;
static HLEHelperThread *accessThread = nullptr;
static const char *accessThreadState = "initial";

static void CleanupDialogThreads() {
if (accessThread && accessThread->Stopped()) {
delete accessThread;
accessThread = nullptr;
static void CleanupDialogThreads(bool force = false) {
if (accessThread) {
if (accessThread->Stopped()) {
delete accessThread;
accessThread = nullptr;
accessThreadState = "cleaned up";
} else if (force) {
ERROR_LOG_REPORT(SCEUTILITY, "Utility access thread still running, state: %s, dialog=%d/%d", accessThreadState, currentDialogType, currentDialogActive);

// Try to force shutdown anyway.
accessThread->Terminate();
delete accessThread;
accessThread = nullptr;
accessThreadState = "force terminated";
// Try to unlock in case other dialog was shutting down.
KernelVolatileMemUnlock(0);
}
}
}

static void ActivateDialog(UtilityDialogType type) {
CleanupDialogThreads();
if (!currentDialogActive) {
currentDialogType = type;
currentDialogActive = true;
// So that we log the next one.
oldStatus = -1;
}
CleanupDialogThreads();
}

static void DeactivateDialog() {
CleanupDialogThreads();
if (currentDialogActive) {
currentDialogActive = false;
}
CleanupDialogThreads();
}

static PSPDialog *CurrentDialog(UtilityDialogType type) {
Expand Down Expand Up @@ -241,6 +255,8 @@ void __UtilityDoState(PointerWrap &p) {
Do(p, hasAccessThread);
if (hasAccessThread) {
Do(p, accessThread);
if (p.mode == p.MODE_READ)
accessThreadState = "from save state";
}
} else {
hasAccessThread = false;
Expand All @@ -250,6 +266,7 @@ void __UtilityDoState(PointerWrap &p) {
accessThread->Forget();
delete accessThread;
accessThread = nullptr;
accessThreadState = "cleared from save state";
}
}

Expand All @@ -264,6 +281,7 @@ void __UtilityShutdown() {
if (accessThread) {
delete accessThread;
accessThread = nullptr;
accessThreadState = "shutdown";
}

delete saveDialog;
Expand Down Expand Up @@ -299,10 +317,10 @@ void UtilityDialogInitialize(UtilityDialogType type, int delayUs, int priority)
(u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityInitDialog"),
};

CleanupDialogThreads();
_assert_(accessThread == nullptr);
CleanupDialogThreads(true);
accessThread = new HLEHelperThread("ScePafJob", insts, (uint32_t)ARRAY_SIZE(insts), priority, 0x200);
accessThread->Start(partDelay, 0);
accessThreadState = "initializing";
}

void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority) {
Expand All @@ -325,12 +343,12 @@ void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority) {
(u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityFinishDialog"),
};

CleanupDialogThreads();
_assert_(accessThread == nullptr);
CleanupDialogThreads(true);
bool prevInterrupts = __InterruptsEnabled();
__DisableInterrupts();
accessThread = new HLEHelperThread("ScePafJob", insts, (uint32_t)ARRAY_SIZE(insts), priority, 0x200);
accessThread->Start(partDelay, 0);
accessThreadState = "shutting down";
if (prevInterrupts)
__EnableInterrupts();
}
Expand All @@ -349,13 +367,15 @@ static int UtilityWorkUs(int us) {

static int UtilityInitDialog(int type) {
PSPDialog *dialog = CurrentDialog((UtilityDialogType)type);
accessThreadState = "init finished";
if (dialog)
return hleLogSuccessI(SCEUTILITY, dialog->FinishInit());
return hleLogError(SCEUTILITY, 0, "invalid dialog type?");
}

static int UtilityFinishDialog(int type) {
PSPDialog *dialog = CurrentDialog((UtilityDialogType)type);
accessThreadState = "shutdown finished";
if (dialog)
return hleLogSuccessI(SCEUTILITY, dialog->FinishShutdown());
return hleLogError(SCEUTILITY, 0, "invalid dialog type?");
Expand All @@ -367,6 +387,9 @@ static int sceUtilitySavedataInitStart(u32 paramAddr) {
WARN_LOG(SCEUTILITY, "Yugioh Savedata Correction");
if (accessThread) {
accessThread->Terminate();
delete accessThread;
accessThread = nullptr;
accessThreadState = "terminated";
// Try to unlock in case other dialog was shutting down.
KernelVolatileMemUnlock(0);
}
Expand Down

0 comments on commit 570d84f

Please sign in to comment.