rosalina: fix gdb/input redir hanging if no internet & fix recovering from failures

This commit is contained in:
TuxSH 2020-04-27 21:58:40 +01:00
parent b551061264
commit 7dfa83b8c0
8 changed files with 88 additions and 21 deletions

View File

@ -68,10 +68,11 @@ typedef struct sock_server
sock_free_func free; sock_free_func free;
Handle shall_terminate_event; Handle shall_terminate_event;
Result init_result;
} sock_server; } sock_server;
Result server_init(struct sock_server *serv); Result server_init(struct sock_server *serv);
void server_bind(struct sock_server *serv, u16 port); Result server_bind(struct sock_server *serv, u16 port);
void server_run(struct sock_server *serv); void server_run(struct sock_server *serv);
void server_kill_connections(struct sock_server *serv); void server_kill_connections(struct sock_server *serv);
void server_set_should_close_all(struct sock_server *serv); void server_set_should_close_all(struct sock_server *serv);

View File

@ -74,13 +74,14 @@ void GDB_DecrementServerReferenceCount(GDBServer *server)
void GDB_RunServer(GDBServer *server) void GDB_RunServer(GDBServer *server)
{ {
server_bind(&server->super, GDB_PORT_BASE); Result res = server_bind(&server->super, GDB_PORT_BASE);
server_bind(&server->super, GDB_PORT_BASE + 1); if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 1);
server_bind(&server->super, GDB_PORT_BASE + 2); if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 2);
server_bind(&server->super, GDB_PORT_BASE + 3); // next application if(R_SUCCEEDED(res)) res = server_bind(&server->super, GDB_PORT_BASE + 3); // next application
server_run(&server->super); if(R_SUCCEEDED(res))
server_run(&server->super);
} }
void GDB_LockAllContexts(GDBServer *server) void GDB_LockAllContexts(GDBServer *server)

View File

@ -55,17 +55,38 @@ int inputRedirectionStartResult;
void inputRedirectionThreadMain(void) void inputRedirectionThreadMain(void)
{ {
Result res = 0; Result res = 0;
inputRedirectionStartResult = 0;
res = miniSocInit(); res = miniSocInit();
if(R_FAILED(res)) if(R_FAILED(res))
{
// Socket services broken
inputRedirectionStartResult = res;
miniSocExit();
// Still signal the event
svcSignalEvent(inputRedirectionThreadStartedEvent);
return; return;
}
int sock = socSocket(AF_INET, SOCK_DGRAM, 0); int sock = socSocket(AF_INET, SOCK_DGRAM, 0);
while(sock == -1) u32 tries = 15;
while(sock == -1 && --tries > 0)
{ {
svcSleepThread(1000 * 0000 * 0000LL); svcSleepThread(100 * 1000 * 1000LL);
sock = socSocket(AF_INET, SOCK_DGRAM, 0); sock = socSocket(AF_INET, SOCK_DGRAM, 0);
} }
if (sock < -10000 || tries == 0) {
// Socket services broken
inputRedirectionStartResult = -1;
miniSocExit();
// Still signal the event
svcSignalEvent(inputRedirectionThreadStartedEvent);
return;
}
struct sockaddr_in saddr; struct sockaddr_in saddr;
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(4950); saddr.sin_port = htons(4950);
@ -76,6 +97,9 @@ void inputRedirectionThreadMain(void)
socClose(sock); socClose(sock);
miniSocExit(); miniSocExit();
inputRedirectionStartResult = res; inputRedirectionStartResult = res;
// Still signal the event
svcSignalEvent(inputRedirectionThreadStartedEvent);
return; return;
} }
@ -125,8 +149,11 @@ void inputRedirectionThreadMain(void)
srvPublishToSubscriber(0x203, 0); srvPublishToSubscriber(0x203, 0);
} }
} }
else if(pollres < -10000)
break;
} }
inputRedirectionEnabled = false;
struct linger linger; struct linger linger;
linger.l_onoff = 1; linger.l_onoff = 1;
linger.l_linger = 0; linger.l_linger = 0;
@ -147,6 +174,8 @@ Result InputRedirection_DoOrUndoPatches(void)
Handle processHandle; Handle processHandle;
Result res = OpenProcessByName("hid", &processHandle); Result res = OpenProcessByName("hid", &processHandle);
static bool hidPatched = false;
static bool irPatched = false;
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
@ -173,11 +202,12 @@ Result InputRedirection_DoOrUndoPatches(void)
static u32 *hidRegPatchOffsets[2]; static u32 *hidRegPatchOffsets[2];
static u32 *hidPatchJumpLoc; static u32 *hidPatchJumpLoc;
if(inputRedirectionEnabled) if(hidPatched)
{ {
memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidRegPatchOffsets[0], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue)); memcpy(hidRegPatchOffsets[1], &hidOrigRegisterAndValue, sizeof(hidOrigRegisterAndValue));
memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode)); memcpy(hidPatchJumpLoc, &hidOrigCode, sizeof(hidOrigCode));
hidPatched = false;
} }
else else
{ {
@ -218,6 +248,7 @@ Result InputRedirection_DoOrUndoPatches(void)
*off = *off2 = hidDataPhys; *off = *off2 = hidDataPhys;
memcpy(off3, &hidHook, sizeof(hidHook)); memcpy(off3, &hidHook, sizeof(hidHook));
hidPatched = true;
} }
} }
@ -264,7 +295,7 @@ Result InputRedirection_DoOrUndoPatches(void)
static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc; static u32 *irHookLoc, *irWaitSyncLoc, *irCppFlagLoc;
if(inputRedirectionEnabled) if(irPatched)
{ {
memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode)); memcpy(irHookLoc, &irOrigReadingCode, sizeof(irOrigReadingCode));
if(useOldSyncCode) if(useOldSyncCode)
@ -272,6 +303,8 @@ Result InputRedirection_DoOrUndoPatches(void)
else else
memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode)); memcpy(irWaitSyncLoc, &irOrigWaitSyncCode, sizeof(irOrigWaitSyncCode));
memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode)); memcpy(irCppFlagLoc, &irOrigCppFlagCode, sizeof(irOrigCppFlagCode));
irPatched = false;
} }
else else
{ {
@ -331,6 +364,8 @@ Result InputRedirection_DoOrUndoPatches(void)
// This NOPs out a flag check in ir:user's CPP emulation // This NOPs out a flag check in ir:user's CPP emulation
*irCppFlagLoc = 0xE3150000; // tst r5, #0 *irCppFlagLoc = 0xE3150000; // tst r5, #0
irPatched = true;
} }
} }

View File

@ -115,16 +115,18 @@ void DebuggerMenu_EnableDebugger(void)
if(!done) if(!done)
{ {
res = GDB_InitializeServer(&gdbServer); res = GDB_InitializeServer(&gdbServer);
Handle handles[3] = { gdbServer.super.started_event, gdbServer.super.shall_terminate_event, terminationRequestEvent };
s32 idx;
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
debuggerCreateSocketThread(); debuggerCreateSocketThread();
debuggerCreateDebugThread(); debuggerCreateDebugThread();
res = svcWaitSynchronization(gdbServer.super.started_event, 10 * 1000 * 1000 * 1000LL); res = svcWaitSynchronizationN(&idx, handles, 3, false, 10 * 1000 * 1000 * 1000LL);
if(res == 0) res = gdbServer.super.init_result;
} }
if(res != 0) if(res != 0)
sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res); sprintf(buf, "Starting debugger... failed (0x%08lx).", (u32)res);
done = true; done = true;
} }
if(res == 0) if(res == 0)

View File

@ -288,7 +288,12 @@ void MiscellaneousMenu_InputRedirection(void)
res = (Result)inputRedirectionStartResult; res = (Result)inputRedirectionStartResult;
if(res != 0) if(res != 0)
{
svcCloseHandle(inputRedirectionThreadStartedEvent);
InputRedirection_DoOrUndoPatches(); InputRedirection_DoOrUndoPatches();
inputRedirectionEnabled = false;
}
inputRedirectionStartResult = 0;
} }
} }

View File

@ -10,7 +10,8 @@
#include <3ds/ipc.h> #include <3ds/ipc.h>
#include <3ds/os.h> #include <3ds/os.h>
#include <3ds/synchronization.h> #include <3ds/synchronization.h>
#include "memory.h" #include <3ds/result.h>
#include <string.h>
s32 _net_convert_error(s32 sock_retval); s32 _net_convert_error(s32 sock_retval);
@ -167,7 +168,7 @@ int socSocket(int domain, int type, int protocol)
if(ret != 0) if(ret != 0)
{ {
//errno = SYNC_ERROR; //errno = SYNC_ERROR;
return ret; return R_FAILED(ret) ? ret : -1;
} }
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];
@ -389,7 +390,7 @@ int socPoll(struct pollfd *fds, nfds_t nfds, int timeout)
staticbufs[1] = saved_threadstorage[1]; staticbufs[1] = saved_threadstorage[1];
if(ret != 0) { if(ret != 0) {
return ret; return R_FAILED(ret) ? ret : -1;
} }
ret = (int)cmdbuf[1]; ret = (int)cmdbuf[1];

View File

@ -104,6 +104,11 @@ Result ntpGetTimeStamp(time_t *outTimestamp)
return res; return res;
int sock = socSocket(AF_INET, SOCK_DGRAM, 0); int sock = socSocket(AF_INET, SOCK_DGRAM, 0);
if (sock < -10000) {
// Socket services broken
return sock;
}
struct sockaddr_in servAddr = {0}; // Server address data structure. struct sockaddr_in servAddr = {0}; // Server address data structure.
NtpPacket packet = {0}; NtpPacket packet = {0};

View File

@ -101,29 +101,36 @@ Result server_init(struct sock_server *serv)
return svcCreateEvent(&serv->shall_terminate_event, RESET_STICKY); return svcCreateEvent(&serv->shall_terminate_event, RESET_STICKY);
} }
void server_bind(struct sock_server *serv, u16 port) Result server_bind(struct sock_server *serv, u16 port)
{ {
int server_sockfd; int server_sockfd;
Handle handles[2] = { terminationRequestEvent, serv->shall_terminate_event }; Handle handles[2] = { terminationRequestEvent, serv->shall_terminate_event };
s32 idx = -1; s32 idx = -1;
server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0);
int res;
while(server_sockfd == -1) int res;
u32 tries = 15;
while(server_sockfd == -1 && --tries > 0)
{ {
if(svcWaitSynchronizationN(&idx, handles, 2, false, 100 * 1000 * 1000LL) == 0) if(svcWaitSynchronizationN(&idx, handles, 2, false, 100 * 1000 * 1000LL) == 0)
return; return -1;
server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0);
} }
if (server_sockfd < -10000 || tries == 0) {
// Socket services broken
serv->init_result = -1;
svcSignalEvent(serv->shall_terminate_event);
return -1;
}
struct sockaddr_in saddr; struct sockaddr_in saddr;
saddr.sin_family = AF_INET; saddr.sin_family = AF_INET;
saddr.sin_port = htons(port); saddr.sin_port = htons(port);
saddr.sin_addr.s_addr = socGethostid(); saddr.sin_addr.s_addr = socGethostid();
res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in));
if(res == 0) if(res == 0)
{ {
res = socListen(server_sockfd, 2); res = socListen(server_sockfd, 2);
@ -143,6 +150,15 @@ void server_bind(struct sock_server *serv, u16 port)
serv->ctx_ptrs[idx] = new_ctx; serv->ctx_ptrs[idx] = new_ctx;
} }
} }
if (res != 0) {
// Socket services broken
serv->init_result = res;
svcSignalEvent(serv->shall_terminate_event);
return res;
}
return 0;
} }
static bool server_should_exit(struct sock_server *serv) static bool server_should_exit(struct sock_server *serv)
@ -171,7 +187,7 @@ void server_run(struct sock_server *serv)
fds[i].revents = 0; fds[i].revents = 0;
int pollres = socPoll(fds, serv->nfds, 50); int pollres = socPoll(fds, serv->nfds, 50);
if(server_should_exit(serv)) if(server_should_exit(serv) || pollres < -10000)
goto abort_connections; goto abort_connections;
for(nfds_t i = 0; pollres > 0 && i < serv->nfds; i++) for(nfds_t i = 0; pollres > 0 && i < serv->nfds; i++)
@ -256,6 +272,7 @@ abort_connections:
server_kill_connections(serv); server_kill_connections(serv);
serv->running = false; serv->running = false;
svcClearEvent(serv->started_event); svcClearEvent(serv->started_event);
svcSignalEvent(serv->shall_terminate_event);
} }
void server_set_should_close_all(struct sock_server *serv) void server_set_should_close_all(struct sock_server *serv)