rosalina: fix gdb/input redir hanging if no internet & fix recovering from failures
This commit is contained in:
parent
b551061264
commit
7dfa83b8c0
@ -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);
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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];
|
||||||
|
@ -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};
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Reference in New Issue
Block a user