rosalina & pm: properly shutdown when debugger, input redir (but not both) and force connection are enabled

This commit is contained in:
TuxSH 2020-04-28 01:31:29 +01:00
parent 8c54613e44
commit 44cd3928fb
10 changed files with 129 additions and 74 deletions

View File

@ -311,6 +311,11 @@ ProcessData *terminateAllProcesses(u32 callerPid, s64 timeout)
ProcessList_Lock(&g_manager.processList); ProcessList_Lock(&g_manager.processList);
// Send custom notification to at least Rosalina to make it relinquish some non-KIP services handles, stop the debugger, etc.
if (numKips >= 6) {
notifySubscribers(0x1001);
}
// Send notification 0x100 to the currently running application // Send notification 0x100 to the currently running application
if (g_manager.runningApplicationData != NULL) { if (g_manager.runningApplicationData != NULL) {
g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED; g_manager.runningApplicationData->flags &= ~PROCESSFLAG_DEPENDENCIES_LOADED;

View File

@ -36,4 +36,5 @@ extern int inputRedirectionStartResult;
MyThread *inputRedirectionCreateThread(void); MyThread *inputRedirectionCreateThread(void);
void inputRedirectionThreadMain(void); void inputRedirectionThreadMain(void);
Result InputRedirection_Disable(s64 timeout);
Result InputRedirection_DoOrUndoPatches(void); Result InputRedirection_DoOrUndoPatches(void);

View File

@ -32,6 +32,8 @@
extern Menu debuggerMenu; extern Menu debuggerMenu;
void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata); void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata);
Result debuggerDisable(s64 timeout);
void DebuggerMenu_EnableDebugger(void); void DebuggerMenu_EnableDebugger(void);
void DebuggerMenu_DisableDebugger(void); void DebuggerMenu_DisableDebugger(void);
void DebuggerMenu_DebugNextApplicationByForce(void); void DebuggerMenu_DebugNextApplicationByForce(void);

View File

@ -18,13 +18,10 @@
#include <errno.h> #include <errno.h>
#define SYNC_ERROR ENODEV #define SYNC_ERROR ENODEV
extern Handle SOCU_handle;
extern Handle socMemhandle;
extern bool miniSocEnabled; extern bool miniSocEnabled;
Result miniSocInit(); Result miniSocInit(void);
Result miniSocExitDirect(void);
Result miniSocExit(void); Result miniSocExit(void);
s32 _net_convert_error(s32 sock_retval); s32 _net_convert_error(s32 sock_retval);

View File

@ -159,14 +159,30 @@ void inputRedirectionThreadMain(void)
linger.l_linger = 0; linger.l_linger = 0;
socSetsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)); socSetsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger));
socClose(sock); socClose(sock);
miniSocExit(); miniSocExit();
} }
void hidCodePatchFunc(void); void hidCodePatchFunc(void);
void irCodePatchFunc(void); void irCodePatchFunc(void);
Result InputRedirection_Disable(s64 timeout)
{
if(!inputRedirectionEnabled)
return 0;
Result res = InputRedirection_DoOrUndoPatches();
if(R_FAILED(res))
return res;
inputRedirectionEnabled = false;
res = MyThread_Join(&inputRedirectionThread, timeout);
svcCloseHandle(inputRedirectionThreadStartedEvent);
return res;
}
Result InputRedirection_DoOrUndoPatches(void) Result InputRedirection_DoOrUndoPatches(void)
{ {
s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize; s64 startAddress, textTotalRoundedSize, rodataTotalRoundedSize, dataTotalRoundedSize;

View File

@ -38,6 +38,9 @@
#include "menus/debugger.h" #include "menus/debugger.h"
#include "menus/screen_filters.h" #include "menus/screen_filters.h"
#include "menus/cheats.h" #include "menus/cheats.h"
#include "menus/sysconfig.h"
#include "input_redirection.h"
#include "minisoc.h"
#include "task_runner.h" #include "task_runner.h"
@ -161,6 +164,26 @@ static void handleTermNotification(u32 notificationId)
svcSignalEvent(terminationRequestEvent); svcSignalEvent(terminationRequestEvent);
} }
static void relinquishConnectionSessions(u32 notificationId)
{
(void)notificationId;
// Might be subject to a race condition, but heh.
// Disable input redirection
InputRedirection_Disable(100 * 1000 * 1000LL);
// Ask the debugger to terminate in approx 2 * 100ms
debuggerDisable(100 * 1000 * 1000LL);
// Kill the ac session if needed
if(isConnectionForced)
{
acExit();
isConnectionForced = false;
SysConfigMenu_UpdateStatus(true);
}
}
static void handleNextApplicationDebuggedByForce(u32 notificationId) static void handleNextApplicationDebuggedByForce(u32 notificationId)
{ {
(void)notificationId; (void)notificationId;
@ -175,7 +198,9 @@ static const ServiceManagerServiceEntry services[] = {
static const ServiceManagerNotificationEntry notifications[] = { static const ServiceManagerNotificationEntry notifications[] = {
{ 0x100 , handleTermNotification }, { 0x100 , handleTermNotification },
//{ 0x103 , relinquishConnectionSessions }, // Sleep mode entry <=== causes issues
{ 0x1000, handleNextApplicationDebuggedByForce }, { 0x1000, handleNextApplicationDebuggedByForce },
{ 0x1001, relinquishConnectionSessions },
{ 0x000, NULL }, { 0x000, NULL },
}; };

View File

@ -84,6 +84,30 @@ void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata)
GDB_UnlockAllContexts(&gdbServer); GDB_UnlockAllContexts(&gdbServer);
} }
Result debuggerDisable(s64 timeout)
{
Result res = 0;
bool initialized = gdbServer.referenceCount != 0;
if(initialized)
{
svcSignalEvent(gdbServer.super.shall_terminate_event);
server_kill_connections(&gdbServer.super);
res = MyThread_Join(&debuggerDebugThread, timeout);
if(res == 0)
res = MyThread_Join(&debuggerSocketThread, timeout);
Handle dummy = 0;
PMDBG_RunQueuedProcess(&dummy);
svcCloseHandle(dummy);
PMDBG_DebugNextApplicationByForce(false);
nextApplicationGdbCtx = NULL;
svcKernelSetState(0x10000, 2);
}
return res;
}
void DebuggerMenu_EnableDebugger(void) void DebuggerMenu_EnableDebugger(void)
{ {
bool done = false, alreadyEnabled = gdbServer.super.running; bool done = false, alreadyEnabled = gdbServer.super.running;
@ -144,27 +168,10 @@ void DebuggerMenu_EnableDebugger(void)
void DebuggerMenu_DisableDebugger(void) void DebuggerMenu_DisableDebugger(void)
{ {
bool initialized = gdbServer.referenceCount != 0; bool initialized = gdbServer.referenceCount != 0;
Result res = 0;
Result res = initialized ? debuggerDisable(2 * 1000 * 1000 * 1000LL) : 0;
char buf[65]; char buf[65];
if(initialized)
{
svcSignalEvent(gdbServer.super.shall_terminate_event);
server_kill_connections(&gdbServer.super);
//server_set_should_close_all(&gdbServer.super);
res = MyThread_Join(&debuggerDebugThread, 2 * 1000 * 1000 * 1000LL);
if(res == 0)
res = MyThread_Join(&debuggerSocketThread, 2 * 1000 * 1000 * 1000LL);
Handle dummy = 0;
PMDBG_RunQueuedProcess(&dummy);
svcCloseHandle(dummy);
PMDBG_DebugNextApplicationByForce(false);
nextApplicationGdbCtx = NULL;
svcKernelSetState(0x10000, 2);
}
if(res != 0) if(res != 0)
sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res); sprintf(buf, "Failed to disable debugger (0x%08lx).", (u32)res);

View File

@ -221,7 +221,6 @@ void MiscellaneousMenu_SaveSettings(void)
void MiscellaneousMenu_InputRedirection(void) void MiscellaneousMenu_InputRedirection(void)
{ {
static MyThread *inputRedirectionThread = NULL;
bool done = false; bool done = false;
Result res; Result res;
@ -231,11 +230,7 @@ void MiscellaneousMenu_InputRedirection(void)
if(wasEnabled) if(wasEnabled)
{ {
res = InputRedirection_DoOrUndoPatches(); res = InputRedirection_Disable(5 * 1000 * 1000 * 1000LL);
inputRedirectionEnabled = false;
res = MyThread_Join(inputRedirectionThread, 5 * 1000 * 1000 * 1000LL);
svcCloseHandle(inputRedirectionThreadStartedEvent);
if(res != 0) if(res != 0)
sprintf(buf, "Failed to stop InputRedirection (0x%08lx).", (u32)res); sprintf(buf, "Failed to stop InputRedirection (0x%08lx).", (u32)res);
else else
@ -282,7 +277,7 @@ void MiscellaneousMenu_InputRedirection(void)
res = svcCreateEvent(&inputRedirectionThreadStartedEvent, RESET_STICKY); res = svcCreateEvent(&inputRedirectionThreadStartedEvent, RESET_STICKY);
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
inputRedirectionThread = inputRedirectionCreateThread(); inputRedirectionCreateThread();
res = svcWaitSynchronization(inputRedirectionThreadStartedEvent, 10 * 1000 * 1000 * 1000LL); res = svcWaitSynchronization(inputRedirectionThreadStartedEvent, 10 * 1000 * 1000 * 1000LL);
if(res == 0) if(res == 0)
res = (Result)inputRedirectionStartResult; res = (Result)inputRedirectionStartResult;

View File

@ -13,6 +13,14 @@
#include <3ds/result.h> #include <3ds/result.h>
#include <string.h> #include <string.h>
s32 miniSocRefCount = 0;
static u32 socContextAddr = 0x08000000;
static u32 socContextSize = 0x60000;
static Handle miniSocHandle;
static Handle miniSocMemHandle;
bool miniSocEnabled = false;
s32 _net_convert_error(s32 sock_retval); s32 _net_convert_error(s32 sock_retval);
static Result SOCU_Initialize(Handle memhandle, u32 memsize) static Result SOCU_Initialize(Handle memhandle, u32 memsize)
@ -26,7 +34,7 @@ static Result SOCU_Initialize(Handle memhandle, u32 memsize)
cmdbuf[4] = IPC_Desc_SharedHandles(1); cmdbuf[4] = IPC_Desc_SharedHandles(1);
cmdbuf[5] = memhandle; cmdbuf[5] = memhandle;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
return ret; return ret;
@ -40,22 +48,14 @@ static Result SOCU_Shutdown(void)
cmdbuf[0] = IPC_MakeHeader(0x19,0,0); // 0x190000 cmdbuf[0] = IPC_MakeHeader(0x19,0,0); // 0x190000
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
return ret; return ret;
return cmdbuf[1]; return cmdbuf[1];
} }
static s32 miniSocRefCount = 0; Result miniSocInit(void)
static u32 socContextAddr = 0x08000000;
static u32 socContextSize = 0x60000;
// SOCU_handle from ctrulib
// socMemhandle from ctrulib
bool miniSocEnabled = false;
Result miniSocInit()
{ {
if(AtomicPostIncrement(&miniSocRefCount)) if(AtomicPostIncrement(&miniSocRefCount))
return 0; return 0;
@ -72,7 +72,7 @@ Result miniSocInit()
goto cleanup; goto cleanup;
} }
ret = srvGetServiceHandle(&SOCU_handle, "soc:U"); ret = srvGetServiceHandle(&miniSocHandle, "soc:U");
if(ret != 0) goto cleanup; if(ret != 0) goto cleanup;
ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE);
@ -80,12 +80,12 @@ Result miniSocInit()
socContextAddr = tmp; socContextAddr = tmp;
ret = svcCreateMemoryBlock(&socMemhandle, (u32)socContextAddr, socContextSize, 0, 3); ret = svcCreateMemoryBlock(&miniSocMemHandle, (u32)socContextAddr, socContextSize, 0, 3);
if(ret != 0) goto cleanup; if(ret != 0) goto cleanup;
ret = SOCU_Initialize(socMemhandle, socContextSize); ret = SOCU_Initialize(miniSocMemHandle, socContextSize);
if(ret != 0) goto cleanup; if(ret != 0) goto cleanup;
svcKernelSetState(0x10000, 2); svcKernelSetState(0x10000, 2);
@ -95,17 +95,17 @@ Result miniSocInit()
cleanup: cleanup:
AtomicDecrement(&miniSocRefCount); AtomicDecrement(&miniSocRefCount);
if(socMemhandle != 0) if(miniSocMemHandle != 0)
{ {
svcCloseHandle(socMemhandle); svcCloseHandle(miniSocMemHandle);
socMemhandle = 0; miniSocMemHandle = 0;
} }
if(SOCU_handle != 0) if(miniSocHandle != 0)
{ {
SOCU_Shutdown(); SOCU_Shutdown();
svcCloseHandle(SOCU_handle); svcCloseHandle(miniSocHandle);
SOCU_handle = 0; miniSocHandle = 0;
} }
if(tmp != 0) if(tmp != 0)
@ -114,21 +114,19 @@ cleanup:
return ret; return ret;
} }
Result miniSocExit(void) Result miniSocExitDirect(void)
{ {
if(AtomicDecrement(&miniSocRefCount)) //if (miniSocRefCount != 0) __builtin_trap();
return 0;
Result ret = 0; Result ret = 0;
u32 tmp; u32 tmp;
svcCloseHandle(socMemhandle); svcCloseHandle(miniSocMemHandle);
socMemhandle = 0; miniSocMemHandle = 0;
ret = SOCU_Shutdown(); ret = SOCU_Shutdown();
svcCloseHandle(SOCU_handle); svcCloseHandle(miniSocHandle);
SOCU_handle = 0; miniSocHandle = 0;
svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE); svcControlMemory(&tmp, socContextAddr, socContextAddr, socContextSize, MEMOP_FREE, MEMPERM_DONTCARE);
if(ret == 0) if(ret == 0)
@ -139,6 +137,14 @@ Result miniSocExit(void)
return ret; return ret;
} }
Result miniSocExit(void)
{
if(!miniSocEnabled || AtomicDecrement(&miniSocRefCount))
return 0;
return miniSocExitDirect();
}
int socSocket(int domain, int type, int protocol) int socSocket(int domain, int type, int protocol)
{ {
int ret = 0; int ret = 0;
@ -164,7 +170,7 @@ int socSocket(int domain, int type, int protocol)
cmdbuf[3] = protocol; cmdbuf[3] = protocol;
cmdbuf[4] = IPC_Desc_CurProcessId(); cmdbuf[4] = IPC_Desc_CurProcessId();
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
{ {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
@ -214,7 +220,7 @@ int socBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0); cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
cmdbuf[6] = (u32)tmpaddr; cmdbuf[6] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return ret;
@ -242,7 +248,7 @@ int socListen(int sockfd, int max_connections)
cmdbuf[2] = (u32)max_connections; cmdbuf[2] = (u32)max_connections;
cmdbuf[3] = IPC_Desc_CurProcessId(); cmdbuf[3] = IPC_Desc_CurProcessId();
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) if(ret != 0)
{ {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
@ -284,7 +290,7 @@ int socAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
staticbufs[1] = (u32)tmpaddr; staticbufs[1] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
staticbufs[0] = saved_threadstorage[0]; staticbufs[0] = saved_threadstorage[0];
staticbufs[1] = saved_threadstorage[1]; staticbufs[1] = saved_threadstorage[1];
@ -341,7 +347,7 @@ int socConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0); cmdbuf[5] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
cmdbuf[6] = (u32)tmpaddr; cmdbuf[6] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) return -1; if(ret != 0) return -1;
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
@ -384,7 +390,7 @@ int socPoll(struct pollfd *fds, nfds_t nfds, int timeout)
staticbufs[0] = IPC_Desc_StaticBuffer(size,0); staticbufs[0] = IPC_Desc_StaticBuffer(size,0);
staticbufs[1] = (u32)fds; staticbufs[1] = (u32)fds;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
staticbufs[0] = saved_threadstorage[0]; staticbufs[0] = saved_threadstorage[0];
staticbufs[1] = saved_threadstorage[1]; staticbufs[1] = saved_threadstorage[1];
@ -409,7 +415,7 @@ int socClose(int sockfd)
cmdbuf[1] = (u32)sockfd; cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = IPC_Desc_CurProcessId(); cmdbuf[2] = IPC_Desc_CurProcessId();
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return ret;
@ -441,7 +447,7 @@ int socSetsockopt(int sockfd, int level, int optname, const void *optval, sockle
cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9); cmdbuf[7] = IPC_Desc_StaticBuffer(optlen,9);
cmdbuf[8] = (u32)optval; cmdbuf[8] = (u32)optval;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
return ret; return ret;
} }
@ -465,7 +471,7 @@ long socGethostid(void)
cmdbuf[0] = IPC_MakeHeader(0x16,0,0); // 0x160000 cmdbuf[0] = IPC_MakeHeader(0x16,0,0); // 0x160000
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return -1; return -1;
@ -507,7 +513,7 @@ static ssize_t _socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struc
staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0); staticbufs[0] = IPC_Desc_StaticBuffer(tmp_addrlen,0);
staticbufs[1] = (u32)tmpaddr; staticbufs[1] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
staticbufs[0] = saved_threadstorage[0]; staticbufs[0] = saved_threadstorage[0];
staticbufs[1] = saved_threadstorage[1]; staticbufs[1] = saved_threadstorage[1];
@ -566,7 +572,7 @@ static ssize_t _socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struc
cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2; cmdbuf[0x108>>2] = (tmp_addrlen<<14) | 2;
cmdbuf[0x10c>>2] = (u32)tmpaddr; cmdbuf[0x10c>>2] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return ret;
@ -632,7 +638,7 @@ static ssize_t _socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags,
cmdbuf[9] = IPC_Desc_Buffer(len,IPC_BUFFER_R); cmdbuf[9] = IPC_Desc_Buffer(len,IPC_BUFFER_R);
cmdbuf[10] = (u32)buf; cmdbuf[10] = (u32)buf;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return ret;
@ -686,7 +692,7 @@ static ssize_t _socuipc_cmda(int sockfd, const void *buf, size_t len, int flags,
cmdbuf[9] = IPC_Desc_StaticBuffer(tmp_addrlen,1); cmdbuf[9] = IPC_Desc_StaticBuffer(tmp_addrlen,1);
cmdbuf[10] = (u32)tmpaddr; cmdbuf[10] = (u32)tmpaddr;
ret = svcSendSyncRequest(SOCU_handle); ret = svcSendSyncRequest(miniSocHandle);
if(ret != 0) { if(ret != 0) {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return ret;

View File

@ -301,7 +301,8 @@ void server_kill_connections(struct sock_server *serv)
socClose(fds[i].fd); socClose(fds[i].fd);
fds[i].fd = -1; fds[i].fd = -1;
serv->ctx_ptrs[i]->should_close = true; if(serv->ctx_ptrs[i] != NULL)
serv->ctx_ptrs[i]->should_close = true;
} }
} }