Add client code for new custom pm commands, use them, fix pm race conditions

This commit is contained in:
TuxSH
2019-03-30 18:12:54 +01:00
parent 43b998d37d
commit 22ec031495
8 changed files with 100 additions and 26 deletions

View File

@@ -128,11 +128,16 @@ Result GetTitleExHeaderFlags(ExHeader_Arm11CoreInfo *outCoreInfo, ExHeader_Syste
Result GetCurrentAppTitleId(u64 *outTitleId)
{
ProcessList_Lock(&g_manager.processList);
Result res;
if (g_manager.runningApplicationData != NULL) {
*outTitleId = g_manager.runningApplicationData->titleId;
return 0;
res = 0;
} else {
*outTitleId = 0;
return MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
res = MAKERESULT(RL_TEMPORARY, RS_NOTFOUND, RM_PM, 0x100);
}
ProcessList_Unlock(&g_manager.processList);
return res;
}

View File

@@ -243,6 +243,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
// note: official pm doesn't terminate the proc. if it fails here either, but will because of the svcCloseHandle and the svcRun codepath
}
ProcessList_Lock(&g_manager.processList);
ProcessData *process = *outProcessData;
if (launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION) {
// saved field is different in official pm
@@ -271,6 +272,7 @@ static Result launchTitleImpl(Handle *debug, ProcessData **outProcessData, const
process->flags |= (launchFlags & PMLAUNCHFLAG_NOTIFY_TERMINATION) ? PROCESSFLAG_NOTIFY_TERMINATION : 0;
}
ProcessList_Unlock(&g_manager.processList);
return res;
}
@@ -323,11 +325,12 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
panic(4);
}
ProcessList_Lock(&g_manager.processList);
if (g_manager.runningApplicationData != NULL && (launchFlags & PMLAUNCHFLAG_NORMAL_APPLICATION) != 0) {
ProcessList_Unlock(&g_manager.processList);
return 0xC8A05BF0;
}
ProcessList_Lock(&g_manager.processList);
FOREACH_PROCESS(&g_manager.processList, process) {
if ((process->titleId & ~0xFFULL) == (programInfo->programId & ~0xFFULL)) {
foundProcess = process;
@@ -370,15 +373,18 @@ Result LaunchTitle(u32 *outPid, const FS_ProgramInfo *programInfo, u32 launchFla
Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags)
{
ProcessList_Lock(&g_manager.processList);
if (g_manager.preparingForReboot) {
return 0xC8A05801;
}
if (g_manager.runningApplicationData != NULL) {
ProcessList_Unlock(&g_manager.processList);
return 0xC8A05BF0;
}
if (!(launchFlags & ~PMLAUNCHFLAG_NORMAL_APPLICATION)) {
return 0xD8E05802;
}
ProcessList_Unlock(&g_manager.processList);
bool originallyDebugged = launchFlags & PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION;
@@ -408,11 +414,15 @@ Result LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo
Result LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags)
{
ProcessList_Lock(&g_manager.processList);
if (g_manager.runningApplicationData != NULL) {
ProcessList_Unlock(&g_manager.processList);
return 0xC8A05BF0;
}
assertSuccess(setAppCpuTimeLimit(0));
ProcessList_Unlock(&g_manager.processList);
return LaunchTitle(NULL, programInfo, launchFlags | PMLAUNCHFLAG_LOAD_DEPENDENCIES | PMLAUNCHFLAG_NORMAL_APPLICATION);
}
@@ -421,10 +431,13 @@ Result RunQueuedProcess(Handle *outDebug)
Result res = 0;
StartupInfo si = {0};
ProcessList_Lock(&g_manager.processList);
if (g_manager.debugData == NULL) {
ProcessList_Unlock(&g_manager.processList);
return 0xD8A05804;
} else if ((g_manager.debugData->flags & PROCESSFLAG_NORMAL_APPLICATION) && g_manager.runningApplicationData != NULL) {
// Not in official PM
ProcessList_Unlock(&g_manager.processList);
return 0xC8A05BF0;
}
@@ -455,17 +468,21 @@ Result RunQueuedProcess(Handle *outDebug)
}
ExHeaderInfoHeap_Delete(exheaderInfo);
ProcessList_Unlock(&g_manager.processList);
return res;
}
Result LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags)
{
ProcessList_Lock(&g_manager.processList);
if (g_manager.debugData != NULL) {
ProcessList_Unlock(&g_manager.processList);
return RunQueuedProcess(outDebug);
}
if (g_manager.runningApplicationData != NULL) {
ProcessList_Unlock(&g_manager.processList);
return 0xC8A05BF0;
}
@@ -473,6 +490,8 @@ Result LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 l
g_debugNextApplication = false;
assertSuccess(setAppCpuTimeLimit(0));
ProcessList_Unlock(&g_manager.processList);
Result res = launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo,
(launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE) | PMLAUNCHFLAG_NORMAL_APPLICATION);
@@ -509,9 +528,12 @@ Result LaunchTitleDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32
return LaunchAppDebug(outDebug, programInfo, launchFlags);
}
ProcessList_Lock(&g_manager.processList);
if (g_manager.debugData != NULL) {
ProcessList_Unlock(&g_manager.processList);
return RunQueuedProcess(outDebug);
}
ProcessList_Unlock(&g_manager.processList);
return launchTitleImplWrapper(outDebug, NULL, programInfo, programInfo, launchFlags & ~PMLAUNCHFLAG_USE_UPDATE_TITLE);
}

View File

@@ -27,16 +27,18 @@ static void cleanupProcess(ProcessData *process)
LOADER_UnregisterProgram(process->programHandle);
}
if (process == g_manager.runningApplicationData) {
ProcessList_Lock(&g_manager.processList);
if (g_manager.runningApplicationData != NULL && process->handle == g_manager.runningApplicationData->handle) {
if (IS_N3DS && APPMEMTYPE == 6) {
assertSuccess(resetAppMemLimit());
}
g_manager.runningApplicationData = NULL;
}
if (process == g_manager.debugData) {
if (g_manager.debugData != NULL && process->handle == g_manager.debugData->handle) {
g_manager.debugData = NULL;
}
ProcessList_Unlock(&g_manager.processList);
if (process->flags & PROCESSFLAG_NOTIFY_TERMINATION) {
notifySubscribers(0x110 + process->terminatedNotificationVariation);

View File

@@ -215,9 +215,11 @@ Result TerminateApplication(s64 timeout)
assertSuccess(svcClearEvent(g_manager.allNotifiedTerminationEvent));
g_manager.waitingForTermination = true;
ProcessList_Lock(&g_manager.processList);
if (g_manager.runningApplicationData != NULL) {
terminateProcessImpl(g_manager.runningApplicationData, exheaderInfo);
}
ProcessList_Unlock(&g_manager.processList);
res = commitPendingTerminations(timeout);
@@ -266,6 +268,7 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
ProcessList_Unlock(&g_manager.processList);
}
ProcessList_Lock(&g_manager.processList);
// Send notification 0x100 to the currently running application
if (g_manager.runningApplicationData != NULL) {
g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED;
@@ -274,7 +277,6 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
// Send notification 0x100 to anything but the caller deps or the caller; and *increase* the refcount of the latter if autoloaded
// Ignore KIPs
ProcessList_Lock(&g_manager.processList);
FOREACH_PROCESS(&g_manager.processList, process) {
if (process->flags & PROCESSFLAG_KIP) {
continue;