diff options
author | Morph <39850852+Morph1984@users.noreply.github.com> | 2022-06-13 20:38:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-13 20:38:37 +0200 |
commit | a0407a8e646172392514dd996d62464db64aee83 (patch) | |
tree | b13a559bcb4a9f9641730d58285a56bde6d5cc80 /src | |
parent | Merge pull request #8454 from liamwhite/inaddr-any (diff) | |
parent | yuzu-cmd: ignore bogus timeous from SDL (diff) | |
download | yuzu-a0407a8e646172392514dd996d62464db64aee83.tar yuzu-a0407a8e646172392514dd996d62464db64aee83.tar.gz yuzu-a0407a8e646172392514dd996d62464db64aee83.tar.bz2 yuzu-a0407a8e646172392514dd996d62464db64aee83.tar.lz yuzu-a0407a8e646172392514dd996d62464db64aee83.tar.xz yuzu-a0407a8e646172392514dd996d62464db64aee83.tar.zst yuzu-a0407a8e646172392514dd996d62464db64aee83.zip |
Diffstat (limited to 'src')
-rw-r--r-- | src/core/core.cpp | 6 | ||||
-rw-r--r-- | src/core/core.h | 3 | ||||
-rw-r--r-- | src/core/debugger/debugger.cpp | 55 | ||||
-rw-r--r-- | src/core/debugger/debugger.h | 5 | ||||
-rw-r--r-- | src/core/debugger/debugger_interface.h | 5 | ||||
-rw-r--r-- | src/core/debugger/gdbstub.cpp | 2 | ||||
-rw-r--r-- | src/core/debugger/gdbstub.h | 1 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 1 | ||||
-rw-r--r-- | src/yuzu_cmd/config.cpp | 2 | ||||
-rw-r--r-- | src/yuzu_cmd/default_ini.h | 5 | ||||
-rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 10 | ||||
-rw-r--r-- | src/yuzu_cmd/yuzu.cpp | 9 |
12 files changed, 96 insertions, 8 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 7d974ba65..954136adb 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -493,6 +493,12 @@ void System::Shutdown() { impl->Shutdown(); } +void System::DetachDebugger() { + if (impl->debugger) { + impl->debugger->NotifyShutdown(); + } +} + std::unique_lock<std::mutex> System::StallCPU() { return impl->StallCPU(); } diff --git a/src/core/core.h b/src/core/core.h index 94477206e..5c367349e 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -160,6 +160,9 @@ public: /// Shutdown the emulated system. void Shutdown(); + /// Forcibly detach the debugger if it is running. + void DetachDebugger(); + std::unique_lock<std::mutex> StallCPU(); void UnstallCPU(); diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index 7774ffdef..edf991d71 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) { return received_data; } +enum class SignalType { + Stopped, + ShuttingDown, +}; + +struct SignalInfo { + SignalType type; + Kernel::KThread* thread; +}; + namespace Core { class DebuggerImpl : public DebuggerBackend { @@ -56,7 +66,7 @@ public: ShutdownServer(); } - bool NotifyThreadStopped(Kernel::KThread* thread) { + bool SignalDebugger(SignalInfo signal_info) { std::scoped_lock lk{connection_lock}; if (stopped) { @@ -64,9 +74,13 @@ public: // It should be ignored. return false; } + + // Set up the state. stopped = true; + info = signal_info; - boost::asio::write(signal_pipe, boost::asio::buffer(&thread, sizeof(thread))); + // Write a single byte into the pipe to wake up the debug interface. + boost::asio::write(signal_pipe, boost::asio::buffer(&stopped, sizeof(stopped))); return true; } @@ -124,7 +138,7 @@ private: Common::SetCurrentThreadName("yuzu:Debugger"); // Set up the client signals for new data. - AsyncReceiveInto(signal_pipe, active_thread, [&](auto d) { PipeData(d); }); + AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); }); AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); }); // Stop the emulated CPU. @@ -142,9 +156,28 @@ private: } void PipeData(std::span<const u8> data) { - AllCoreStop(); - UpdateActiveThread(); - frontend->Stopped(active_thread); + switch (info.type) { + case SignalType::Stopped: + // Stop emulation. + AllCoreStop(); + + // Notify the client. + active_thread = info.thread; + UpdateActiveThread(); + frontend->Stopped(active_thread); + + break; + case SignalType::ShuttingDown: + frontend->ShuttingDown(); + + // Wait for emulation to shut down gracefully now. + suspend.reset(); + signal_pipe.close(); + client_socket.shutdown(boost::asio::socket_base::shutdown_both); + LOG_INFO(Debug_GDBStub, "Shut down server"); + + break; + } } void ClientData(std::span<const u8> data) { @@ -246,7 +279,9 @@ private: boost::asio::ip::tcp::socket client_socket; std::optional<std::unique_lock<std::mutex>> suspend; + SignalInfo info; Kernel::KThread* active_thread; + bool pipe_data; bool stopped; std::array<u8, 4096> client_data; @@ -263,7 +298,13 @@ Debugger::Debugger(Core::System& system, u16 port) { Debugger::~Debugger() = default; bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) { - return impl && impl->NotifyThreadStopped(thread); + return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread}); +} + +void Debugger::NotifyShutdown() { + if (impl) { + impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr}); + } } } // namespace Core diff --git a/src/core/debugger/debugger.h b/src/core/debugger/debugger.h index ea36c6ab2..f9738ca3d 100644 --- a/src/core/debugger/debugger.h +++ b/src/core/debugger/debugger.h @@ -35,6 +35,11 @@ public: */ bool NotifyThreadStopped(Kernel::KThread* thread); + /** + * Notify the debugger that a shutdown is being performed now and disconnect. + */ + void NotifyShutdown(); + private: std::unique_ptr<DebuggerImpl> impl; }; diff --git a/src/core/debugger/debugger_interface.h b/src/core/debugger/debugger_interface.h index 35ba0bc61..c0bb4ecaf 100644 --- a/src/core/debugger/debugger_interface.h +++ b/src/core/debugger/debugger_interface.h @@ -67,6 +67,11 @@ public: virtual void Stopped(Kernel::KThread* thread) = 0; /** + * Called when emulation is shutting down. + */ + virtual void ShuttingDown() = 0; + + /** * Called when new data is asynchronously received on the client socket. * A list of actions to perform is returned. */ diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp index f52d78829..52e76f659 100644 --- a/src/core/debugger/gdbstub.cpp +++ b/src/core/debugger/gdbstub.cpp @@ -106,6 +106,8 @@ GDBStub::~GDBStub() = default; void GDBStub::Connected() {} +void GDBStub::ShuttingDown() {} + void GDBStub::Stopped(Kernel::KThread* thread) { SendReply(arch->ThreadStatus(thread, GDB_STUB_SIGTRAP)); } diff --git a/src/core/debugger/gdbstub.h b/src/core/debugger/gdbstub.h index 1bb638187..ec934c77e 100644 --- a/src/core/debugger/gdbstub.h +++ b/src/core/debugger/gdbstub.h @@ -23,6 +23,7 @@ public: void Connected() override; void Stopped(Kernel::KThread* thread) override; + void ShuttingDown() override; std::vector<DebuggerAction> ClientData(std::span<const u8> data) override; private: diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 27f23bcb0..33886e50e 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1591,6 +1591,7 @@ void GMainWindow::ShutdownGame() { AllowOSSleep(); + system->DetachDebugger(); discord_rpc->Pause(); emu_thread->RequestStop(); diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index fc16f0f0c..fc4744fb0 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -344,6 +344,8 @@ void Config::ReadValues() { ReadSetting("Debugging", Settings::values.use_debug_asserts); ReadSetting("Debugging", Settings::values.use_auto_stub); ReadSetting("Debugging", Settings::values.disable_macro_jit); + ReadSetting("Debugging", Settings::values.use_gdbstub); + ReadSetting("Debugging", Settings::values.gdbstub_port); const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); std::stringstream ss(title_list); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 39063e32b..a3b8432f5 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -437,6 +437,11 @@ disable_macro_jit=false # Presents guest frames as they become available. Experimental. # false: Disabled (default), true: Enabled disable_fps_limit=false +# Determines whether to enable the GDB stub and wait for the debugger to attach before running. +# false: Disabled (default), true: Enabled +use_gdbstub=false +# The port to use for the GDB server, if it is enabled. +gdbstub_port=6543 [WebService] # Whether or not to enable telemetry diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 71c413e64..8e38724db 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -162,7 +162,15 @@ void EmuWindow_SDL2::WaitEvent() { SDL_Event event; if (!SDL_WaitEvent(&event)) { - LOG_CRITICAL(Frontend, "SDL_WaitEvent failed: {}", SDL_GetError()); + const char* error = SDL_GetError(); + if (!error || strcmp(error, "") == 0) { + // https://github.com/libsdl-org/SDL/issues/5780 + // Sometimes SDL will return without actually having hit an error condition; + // just ignore it in this case. + return; + } + + LOG_CRITICAL(Frontend, "SDL_WaitEvent failed: {}", error); exit(1); } diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index ab12dd15d..0dce5e274 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -217,10 +217,19 @@ int main(int argc, char** argv) { [](VideoCore::LoadCallbackStage, size_t value, size_t total) {}); } + system.RegisterExitCallback([&] { + // Just exit right away. + exit(0); + }); + void(system.Run()); + if (system.DebuggerEnabled()) { + system.InitializeDebugger(); + } while (emu_window->IsOpen()) { emu_window->WaitEvent(); } + system.DetachDebugger(); void(system.Pause()); system.Shutdown(); |