Skip to content

Commit

Permalink
Instead of having ReplayCommand stash a pointer to the GdbServer
Browse files Browse the repository at this point in the history
…for use by the signal handler, have it store the `stop_replaying_to_target` boolean flag directly and point the `GdbServer` at it.

This will make it easier to refactor further so that `ReplayCommand` never needs to see the `GdbServer` object at all.
  • Loading branch information
rocallahan committed Mar 18, 2024
1 parent 4e33cad commit bc64818
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 24 deletions.
13 changes: 6 additions & 7 deletions src/GdbServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,21 @@ GdbServer::GdbServer(std::unique_ptr<GdbServerConnection>& 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()),
file_scope_pid(0) {
memset(&stop_siginfo, 0, sizeof(stop_siginfo));
}

GdbServer::GdbServer(std::shared_ptr<ReplaySession> session, const Target& target)
GdbServer::GdbServer(std::shared_ptr<ReplaySession> 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)),
Expand Down Expand Up @@ -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
Expand Down Expand 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"
Expand Down Expand Up @@ -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.
Expand Down
16 changes: 6 additions & 10 deletions src/GdbServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<ReplaySession> session, const Target& target);
GdbServer(std::shared_ptr<ReplaySession> 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.
*/
Expand Down Expand Up @@ -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;
Expand Down
11 changes: 4 additions & 7 deletions src/ReplayCommand.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit bc64818

Please sign in to comment.