Fix GDB server crashes

This commit is contained in:
svc64 2023-11-11 17:08:25 +02:00
parent e3b8060417
commit 1684a9d7a2
2 changed files with 39 additions and 49 deletions

View file

@ -27,8 +27,7 @@ namespace Ryujinx.HLE.Debugger
private NetworkStream ReadStream = null; private NetworkStream ReadStream = null;
private NetworkStream WriteStream = null; private NetworkStream WriteStream = null;
private BlockingCollection<IMessage> Messages = new BlockingCollection<IMessage>(1); private BlockingCollection<IMessage> Messages = new BlockingCollection<IMessage>(1);
private Thread SocketThread; private Thread DebuggerThread;
private Thread HandlerThread;
private bool _shuttingDown = false; private bool _shuttingDown = false;
private ulong? cThread; private ulong? cThread;
@ -41,10 +40,8 @@ namespace Ryujinx.HLE.Debugger
ARMeilleure.Optimizations.EnableDebugging = true; ARMeilleure.Optimizations.EnableDebugging = true;
SocketThread = new Thread(SocketReaderThreadMain); DebuggerThread = new Thread(DebuggerThreadMain);
HandlerThread = new Thread(HandlerThreadMain); DebuggerThread.Start();
SocketThread.Start();
HandlerThread.Start();
} }
private IDebuggableProcess DebugProcess => Device.System.DebugGetApplicationProcess(); private IDebuggableProcess DebugProcess => Device.System.DebugGetApplicationProcess();
@ -144,35 +141,29 @@ namespace Ryujinx.HLE.Debugger
} }
} }
private void HandlerThreadMain() private void HandleMessage(IMessage msg)
{ {
while (true) switch (msg)
{ {
switch (Messages.Take()) case BreakInMessage:
{ Logger.Notice.Print(LogClass.GdbStub, "Break-in requested");
case AbortMessage _: CommandQuery();
return; break;
case BreakInMessage _: case SendNackMessage:
Logger.Notice.Print(LogClass.GdbStub, "Break-in requested"); WriteStream.WriteByte((byte)'-');
CommandQuery(); break;
break;
case SendNackMessage _: case CommandMessage {Command: var cmd}:
WriteStream.WriteByte((byte)'-'); Logger.Debug?.Print(LogClass.GdbStub, $"Received Command: {cmd}");
break; WriteStream.WriteByte((byte)'+');
ProcessCommand(cmd);
break;
case CommandMessage {Command: var cmd}: case ThreadBreakMessage {Context: var ctx}:
Logger.Debug?.Print(LogClass.GdbStub, $"Received Command: {cmd}"); DebugProcess.DebugStop();
WriteStream.WriteByte((byte)'+'); Reply($"T05thread:{ctx.ThreadUid:x};");
ProcessCommand(cmd); break;
break;
case ThreadBreakMessage msg:
DebugProcess.DebugStop();
Reply($"T05thread:{msg.Context.ThreadUid:x};");
break;
}
} }
} }
@ -595,15 +586,23 @@ namespace Ryujinx.HLE.Debugger
Reply("E01"); Reply("E01");
} }
private void SocketReaderThreadMain() private void DebuggerThreadMain()
{ {
var endpoint = new IPEndPoint(IPAddress.Any, GdbStubPort); var endpoint = new IPEndPoint(IPAddress.Any, GdbStubPort);
ListenerSocket = new TcpListener(endpoint); ListenerSocket = new TcpListener(endpoint);
ListenerSocket.Start(); ListenerSocket.Start();
Logger.Notice.Print(LogClass.GdbStub, $"Currently waiting on {endpoint} for GDB client"); Logger.Notice.Print(LogClass.GdbStub, $"Currently waiting on {endpoint} for GDB client");
while (true) { while (!_shuttingDown)
ClientSocket = ListenerSocket.AcceptSocket(); {
try
{
ClientSocket = ListenerSocket.AcceptSocket();
}
catch (SocketException)
{
return;
}
ClientSocket.NoDelay = true; ClientSocket.NoDelay = true;
ReadStream = new NetworkStream(ClientSocket, System.IO.FileAccess.Read); ReadStream = new NetworkStream(ClientSocket, System.IO.FileAccess.Read);
WriteStream = new NetworkStream(ClientSocket, System.IO.FileAccess.Write); WriteStream = new NetworkStream(ClientSocket, System.IO.FileAccess.Write);
@ -623,7 +622,7 @@ namespace Ryujinx.HLE.Debugger
Logger.Notice.Print(LogClass.GdbStub, "NACK received!"); Logger.Notice.Print(LogClass.GdbStub, "NACK received!");
continue; continue;
case '\x03': case '\x03':
Messages.Add(new BreakInMessage()); HandleMessage(new BreakInMessage());
break; break;
case '$': case '$':
string cmd = ""; string cmd = "";
@ -640,11 +639,11 @@ namespace Ryujinx.HLE.Debugger
string checksum = $"{(char)ReadStream.ReadByte()}{(char)ReadStream.ReadByte()}"; string checksum = $"{(char)ReadStream.ReadByte()}{(char)ReadStream.ReadByte()}";
if (checksum == $"{CalculateChecksum(cmd):x2}") if (checksum == $"{CalculateChecksum(cmd):x2}")
{ {
Messages.Add(new CommandMessage(cmd)); HandleMessage(new CommandMessage(cmd));
} }
else else
{ {
Messages.Add(new SendNackMessage()); HandleMessage(new SendNackMessage());
} }
break; break;
@ -659,8 +658,11 @@ namespace Ryujinx.HLE.Debugger
eof: eof:
Logger.Notice.Print(LogClass.GdbStub, "GDB client lost connection"); Logger.Notice.Print(LogClass.GdbStub, "GDB client lost connection");
ReadStream.Close(); ReadStream.Close();
ReadStream = null;
WriteStream.Close(); WriteStream.Close();
WriteStream = null;
ClientSocket.Close(); ClientSocket.Close();
ClientSocket = null;
} }
} }
@ -718,18 +720,12 @@ namespace Ryujinx.HLE.Debugger
{ {
_shuttingDown = true; _shuttingDown = true;
if (HandlerThread.IsAlive)
{
Messages.Add(new AbortMessage());
}
ListenerSocket.Stop(); ListenerSocket.Stop();
ClientSocket?.Shutdown(SocketShutdown.Both); ClientSocket?.Shutdown(SocketShutdown.Both);
ClientSocket?.Close(); ClientSocket?.Close();
ReadStream?.Close(); ReadStream?.Close();
WriteStream?.Close(); WriteStream?.Close();
SocketThread.Join(); DebuggerThread.Join();
HandlerThread.Join();
} }
} }

View file

@ -1,6 +0,0 @@
namespace Ryujinx.HLE.Debugger
{
struct AbortMessage : IMessage
{
}
}