diff --git a/src/GdbServer.cc b/src/GdbServer.cc index 69981fd403e..5e948355022 100644 --- a/src/GdbServer.cc +++ b/src/GdbServer.cc @@ -57,7 +57,7 @@ GdbServer::GdbServer(std::unique_ptr& dbg, Task* t) final_event(UINT32_MAX), in_debuggee_end_state(false), failed_restart(false), - stop_replaying_to_target(false), + stop_replaying_to_target(nullptr), interrupt_pending(false), exit_sigkill_pending(false), emergency_debug_session(&t->session()), @@ -65,12 +65,13 @@ GdbServer::GdbServer(std::unique_ptr& dbg, Task* t) memset(&stop_siginfo, 0, sizeof(stop_siginfo)); } -GdbServer::GdbServer(std::shared_ptr session, const Target& target) +GdbServer::GdbServer(std::shared_ptr session, const Target& target, + volatile bool* stop_replaying_to_target) : target(target), final_event(UINT32_MAX), in_debuggee_end_state(false), failed_restart(false), - stop_replaying_to_target(false), + stop_replaying_to_target(stop_replaying_to_target), interrupt_pending(false), exit_sigkill_pending(false), timeline(std::move(session)), @@ -1421,7 +1422,7 @@ bool GdbServer::at_target(ReplayResult& result) { if (!(timeline.can_add_checkpoint() || target_is_exit)) { return false; } - if (stop_replaying_to_target) { + if (stop_replaying_to_target && *stop_replaying_to_target) { return true; } // When we decide to create the debugger, we may end up @@ -1455,7 +1456,7 @@ void GdbServer::activate_debugger() { FrameTime completed_event = next_frame.time() - 1; Task* t = timeline.current_session().current_task(); if (target.event || target.pid) { - if (stop_replaying_to_target) { + if (stop_replaying_to_target && *stop_replaying_to_target) { fprintf(stderr, "\a\n" "--------------------------------------------------\n" " ---> Interrupted; attached to NON-TARGET process %d at event %llu.\n" @@ -1610,8 +1611,6 @@ void GdbServer::restart_session(const GdbRequest& req) { return; } - stop_replaying_to_target = false; - if (req.restart().type == RESTART_FROM_EVENT) { // Note that we don't reset the target pid; we intentionally keep targeting // the same process no matter what is running when we hit the event. diff --git a/src/GdbServer.h b/src/GdbServer.h index cf58a4eb5fd..0dfe26f08f9 100644 --- a/src/GdbServer.h +++ b/src/GdbServer.h @@ -60,21 +60,17 @@ class GdbServer { /** * Create a gdbserver serving the replay of 'session'. + * When `stop_replaying_to_target` is non-null, setting it to true + * (e.g. in a signal handler) will interrupt the replay. */ - GdbServer(std::shared_ptr session, const Target& target); + GdbServer(std::shared_ptr session, const Target& target, + volatile bool* stop_replaying_to_target); /** * Actually run the server. Returns only when the debugger disconnects. */ void serve_replay(const ConnectionFlags& flags); - /** - * Called from a signal handler (or other thread) during serve_replay, - * this will cause the replay-to-target phase to be interrupted and - * debugging started wherever the replay happens to be. - */ - void interrupt_replay_to_target() { stop_replaying_to_target = true; } - /** * Return the register |which|, which may not have a defined value. */ @@ -201,8 +197,8 @@ class GdbServer { bool in_debuggee_end_state; // True when a restart was attempted but didn't succeed. bool failed_restart; - // True when the user has interrupted replaying to a target event. - volatile bool stop_replaying_to_target; + // Set to true when the user has interrupted replaying to a target event. + volatile bool* stop_replaying_to_target; // True when a DREQ_INTERRUPT has been received but not handled, or when // we've restarted and want the first continue to be interrupted immediately. bool interrupt_pending; diff --git a/src/ReplayCommand.cc b/src/ReplayCommand.cc index 6c0427c3d62..be6cf76efe8 100644 --- a/src/ReplayCommand.cc +++ b/src/ReplayCommand.cc @@ -473,13 +473,11 @@ static void handle_SIGINT_in_parent(int sig) { // Just ignore it. } -static GdbServer* server_ptr = nullptr; +static volatile bool stop_replaying_to_target; static void handle_SIGINT_in_child(int sig) { DEBUG_ASSERT(sig == SIGINT); - if (server_ptr) { - server_ptr->interrupt_replay_to_target(); - } + stop_replaying_to_target = true; } static int replay(const string& trace_dir, const ReplayFlags& flags) { @@ -512,7 +510,7 @@ static int replay(const string& trace_dir, const ReplayFlags& flags) { conn_flags.debugger_name = flags.gdb_binary_file_path; conn_flags.keep_listening = flags.keep_listening; conn_flags.serve_files = flags.serve_files; - GdbServer(session, target).serve_replay(conn_flags); + GdbServer(session, target, &stop_replaying_to_target).serve_replay(conn_flags); } // Everything should have been cleaned up by now. @@ -544,9 +542,8 @@ static int replay(const string& trace_dir, const ReplayFlags& flags) { // of the first process (rather than the first exit of a process). target.pid = session->trace_reader().peek_frame().tid(); } - GdbServer server(session, target); + GdbServer server(session, target, &stop_replaying_to_target); - server_ptr = &server; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_RESTART;