summaryrefslogtreecommitdiff
path: root/src/core/debugger/debugger.cpp
diff options
context:
space:
mode:
authorGravatar Liam2022-06-10 09:17:12 -0400
committerGravatar Liam2022-06-10 09:17:12 -0400
commit1f0fee33edf06bb237a952b78b6e117ba81cbdbb (patch)
tree01ce352e9ffbc07cb2b7dc0fd1e1c4ea50298bee /src/core/debugger/debugger.cpp
parentcore/debugger: support operation in yuzu-cmd (diff)
downloadyuzu-1f0fee33edf06bb237a952b78b6e117ba81cbdbb.tar.gz
yuzu-1f0fee33edf06bb237a952b78b6e117ba81cbdbb.tar.xz
yuzu-1f0fee33edf06bb237a952b78b6e117ba81cbdbb.zip
core/debugger: fix a number of shutdown deadlocks
Diffstat (limited to 'src/core/debugger/debugger.cpp')
-rw-r--r--src/core/debugger/debugger.cpp55
1 files changed, 48 insertions, 7 deletions
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index 8d64990ed..1d7f9a775 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -42,6 +42,16 @@ static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer) {
42 return received_data; 42 return received_data;
43} 43}
44 44
45enum class SignalType {
46 Stopped,
47 ShuttingDown,
48};
49
50struct SignalInfo {
51 SignalType type;
52 Kernel::KThread* thread;
53};
54
45namespace Core { 55namespace Core {
46 56
47class DebuggerImpl : public DebuggerBackend { 57class DebuggerImpl : public DebuggerBackend {
@@ -56,7 +66,7 @@ public:
56 ShutdownServer(); 66 ShutdownServer();
57 } 67 }
58 68
59 bool NotifyThreadStopped(Kernel::KThread* thread) { 69 bool SignalDebugger(SignalInfo signal_info) {
60 std::scoped_lock lk{connection_lock}; 70 std::scoped_lock lk{connection_lock};
61 71
62 if (stopped) { 72 if (stopped) {
@@ -64,9 +74,13 @@ public:
64 // It should be ignored. 74 // It should be ignored.
65 return false; 75 return false;
66 } 76 }
77
78 // Set up the state.
67 stopped = true; 79 stopped = true;
80 info = signal_info;
68 81
69 boost::asio::write(signal_pipe, boost::asio::buffer(&thread, sizeof(thread))); 82 // Write a single byte into the pipe to wake up the debug interface.
83 boost::asio::write(signal_pipe, boost::asio::buffer(&stopped, sizeof(stopped)));
70 return true; 84 return true;
71 } 85 }
72 86
@@ -124,7 +138,7 @@ private:
124 Common::SetCurrentThreadName("yuzu:Debugger"); 138 Common::SetCurrentThreadName("yuzu:Debugger");
125 139
126 // Set up the client signals for new data. 140 // Set up the client signals for new data.
127 AsyncReceiveInto(signal_pipe, active_thread, [&](auto d) { PipeData(d); }); 141 AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); });
128 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); }); 142 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); });
129 143
130 // Stop the emulated CPU. 144 // Stop the emulated CPU.
@@ -142,9 +156,28 @@ private:
142 } 156 }
143 157
144 void PipeData(std::span<const u8> data) { 158 void PipeData(std::span<const u8> data) {
145 AllCoreStop(); 159 switch (info.type) {
146 UpdateActiveThread(); 160 case SignalType::Stopped:
147 frontend->Stopped(active_thread); 161 // Stop emulation.
162 AllCoreStop();
163
164 // Notify the client.
165 active_thread = info.thread;
166 UpdateActiveThread();
167 frontend->Stopped(active_thread);
168
169 break;
170 case SignalType::ShuttingDown:
171 frontend->ShuttingDown();
172
173 // Wait for emulation to shut down gracefully now.
174 suspend.reset();
175 signal_pipe.close();
176 client_socket.shutdown(boost::asio::socket_base::shutdown_both);
177 LOG_INFO(Debug_GDBStub, "Shut down server");
178
179 break;
180 }
148 } 181 }
149 182
150 void ClientData(std::span<const u8> data) { 183 void ClientData(std::span<const u8> data) {
@@ -246,7 +279,9 @@ private:
246 boost::asio::ip::tcp::socket client_socket; 279 boost::asio::ip::tcp::socket client_socket;
247 std::optional<std::unique_lock<std::mutex>> suspend; 280 std::optional<std::unique_lock<std::mutex>> suspend;
248 281
282 SignalInfo info;
249 Kernel::KThread* active_thread; 283 Kernel::KThread* active_thread;
284 bool pipe_data;
250 bool stopped; 285 bool stopped;
251 286
252 std::array<u8, 4096> client_data; 287 std::array<u8, 4096> client_data;
@@ -263,7 +298,13 @@ Debugger::Debugger(Core::System& system, u16 port) {
263Debugger::~Debugger() = default; 298Debugger::~Debugger() = default;
264 299
265bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) { 300bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) {
266 return impl && impl->NotifyThreadStopped(thread); 301 return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread});
302}
303
304void Debugger::NotifyShutdown() {
305 if (impl) {
306 impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr});
307 }
267} 308}
268 309
269} // namespace Core 310} // namespace Core