diff --git a/sysmodules/pm/source/launch.c b/sysmodules/pm/source/launch.c index e6a1893..9a391e6 100644 --- a/sysmodules/pm/source/launch.c +++ b/sysmodules/pm/source/launch.c @@ -290,8 +290,16 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const return res; } -Result launchTitleImplWrapper(Handle *outDebug, u32 *outPid, const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags) +static Result launchTitleImplWrapper(Handle *outDebug, u32 *outPid, const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags) { + // Not in official PM, but we need to check here as well to avoid a race condition + ProcessList_Lock(&g_manager.processList); + if (g_manager.runningApplicationData != NULL && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) { + ProcessList_Unlock(&g_manager.processList); + return 0xC8A05BF0; + } + ProcessList_Unlock(&g_manager.processList); + ExHeader_Info *exheaderInfo = ExHeaderInfoHeap_New(); if (exheaderInfo == NULL) { panic(0); @@ -319,7 +327,7 @@ static void LaunchTitleAsync(void *argdata) launchTitleImplWrapper(NULL, NULL, &args->programInfo, &args->programInfoUpdate, args->launchFlags); } -Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFlags) +Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFlags, bool allowAsync) { ProcessData *process, *foundProcess = NULL; bool originallyDebugged = launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION; @@ -362,7 +370,7 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla } return 0; } else { - if (launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION || !(launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION)) { + if (!allowAsync || launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION || !(launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION)) { Result res = launchTitleImplWrapper(NULL, outPid, programInfo, programInfo, launchFlags); if (R_SUCCEEDED(res) && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION)) { g_debugNextApplication = false; @@ -445,7 +453,7 @@ Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags) assertSuccess(setAppCpuTimeLimit(0)); ProcessList_Unlock(&g_manager.processList); - return LaunchTitle(NULL, programInfo, launchFlags | PMLAUNCHFLAG_LOAD_DEPENDENCIES | PMLAUNCHFLAG_NORMAL_APPLICATION); + return LaunchTitle(NULL, programInfo, launchFlags | PMLAUNCHFLAG_LOAD_DEPENDENCIES | PMLAUNCHFLAG_NORMAL_APPLICATION, true); } Result RunQueuedProcess(Handle *outDebug) diff --git a/sysmodules/pm/source/launch.h b/sysmodules/pm/source/launch.h index c982655..04da8da 100644 --- a/sysmodules/pm/source/launch.h +++ b/sysmodules/pm/source/launch.h @@ -9,7 +9,7 @@ enum { PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING = BIT(24), }; -Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFlags); +Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFlags, bool allowAsync); Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags); Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags); Result RunQueuedProcess(Handle *outDebug); @@ -20,5 +20,3 @@ Result autolaunchSysmodules(void); // Custom Result DebugNextApplicationByForce(bool debug); Result LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags); - -Result launchTitleImplWrapper(Handle *outDebug, u32 *outPid, const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags); diff --git a/sysmodules/pm/source/pmapp.c b/sysmodules/pm/source/pmapp.c index fc0b012..565aed4 100644 --- a/sysmodules/pm/source/pmapp.c +++ b/sysmodules/pm/source/pmapp.c @@ -26,7 +26,7 @@ void pmAppHandleCommands(void *ctx) switch (cmdhdr >> 16) { case 1: memcpy(&programInfo, cmdbuf + 1, sizeof(FS_ProgramInfo)); - cmdbuf[1] = LaunchTitle(&pid, &programInfo, cmdbuf[5]); + cmdbuf[1] = LaunchTitle(&pid, &programInfo, cmdbuf[5], true); cmdbuf[2] = pid; cmdbuf[0] = IPC_MakeHeader(1, 2, 0); break; diff --git a/sysmodules/pm/source/termination.c b/sysmodules/pm/source/termination.c index b48b7d1..dd903bf 100644 --- a/sysmodules/pm/source/termination.c +++ b/sysmodules/pm/source/termination.c @@ -6,6 +6,7 @@ #include "exheader_info_heap.h" #include "task_runner.h" #include "launch.h" +#include "reslimit.h" void forceMountSdCard(void) { @@ -440,11 +441,15 @@ static void ChainloadHomebrewDirtyAsync(void *argdata) ProcessList_Unlock(&g_manager.processList); } while (app != NULL); + // There is a small time window where we could fail (with another app spawning) // Since this is a dirty workaround for hb support on SAFE_FIRM, we can opt not to support // launch-from-gamecard/update support. - launchFlags &= ~PMLAUNCHFLAG_USE_UPDATE_TITLE; + // Also clear the debug queue flag, obviously (it'll be reset by the "force next app debug" + // mechanism if needed) + launchFlags &= ~(PMLAUNCHFLAG_USE_UPDATE_TITLE | PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION); launchFlags |= PMLAUNCHFLAGEXT_FAKE_DEPENDENCY_LOADING; - res = launchTitleImplWrapper(NULL, NULL, &programInfo, NULL, launchFlags); + assertSuccess(setAppCpuTimeLimit(0)); + res = LaunchTitle(NULL, &programInfo, launchFlags, false); } }