Dialog: Try to recover on double init, report.

This shouldn't be happening, but is - see #14864.
Let's report the situation and try to avoid a complete crash.
This commit is contained in:
Unknown W. Brackets 2021-09-15 21:06:12 -07:00
parent 433daf1ee8
commit 570d84fb86

View file

@ -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) {
@ -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;
@ -250,6 +266,7 @@ void __UtilityDoState(PointerWrap &p) {
accessThread->Forget();
delete accessThread;
accessThread = nullptr;
accessThreadState = "cleared from save state";
}
}
@ -264,6 +281,7 @@ void __UtilityShutdown() {
if (accessThread) {
delete accessThread;
accessThread = nullptr;
accessThreadState = "shutdown";
}
delete saveDialog;
@ -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) {
@ -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();
}
@ -349,6 +367,7 @@ 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?");
@ -356,6 +375,7 @@ static int UtilityInitDialog(int 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?");
@ -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);
}