From c447ac0bfb51568d4c239dd11e016dc0281ee358 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Mon, 28 Oct 2013 16:39:05 +0000 Subject: [PATCH] infrun.c:handle_inferior_event: Put all ecs->random_signal tests together. I recently added a new ecs->random_signal test after the "switch back to stepped thread" code, and before the stepping tests. Looking at making process_event_stop_test a proper function, I realized it'd be better to keep ecs->random_signal related code together. To do that, I needed to factor out the "switch back to stepped thread" code to a new function, and call it in both the "random signal" and "not random signal" paths. gdb/ 2013-10-28 Pedro Alves * infrun.c (switch_back_to_stepped_thread): New function, factored out from handle_inferior_event. (handle_inferior_event): Adjust to call switch_back_to_stepped_thread. Call it also at the tail of the random signal handling, and return, instead of also handling random signals just before the stepping tests. --- gdb/ChangeLog | 9 +++ gdb/infrun.c | 169 +++++++++++++++++++++++++++----------------------- 2 files changed, 100 insertions(+), 78 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1a0328b5a91..baf9a113c46 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2013-10-28 Pedro Alves + + * infrun.c (switch_back_to_stepped_thread): New function, factored + out from handle_inferior_event. + (handle_inferior_event): Adjust to call + switch_back_to_stepped_thread. Call it also at the tail of the + random signal handling, and return, instead of also handling + random signals just before the stepping tests. + 2013-10-28 Pedro Alves * infrun.c (clear_stop_func): Delete. diff --git a/gdb/infrun.c b/gdb/infrun.c index 8b1b668a41c..0da90ece0fd 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -2439,6 +2439,7 @@ static void check_exception_resume (struct execution_control_state *, static void stop_stepping (struct execution_control_state *ecs); static void prepare_to_wait (struct execution_control_state *ecs); static void keep_going (struct execution_control_state *ecs); +static int switch_back_to_stepped_thread (struct execution_control_state *ecs); /* Callback for iterate over threads. If the thread is stopped, but the user/frontend doesn't know about that yet, go through @@ -4398,6 +4399,16 @@ process_event_stop_test: (leaving the inferior at the step-resume-breakpoint without actually executing it). Either way continue until the breakpoint is really hit. */ + + if (!switch_back_to_stepped_thread (ecs)) + { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: random signal, keep going\n"); + + keep_going (ecs); + } + return; } else { @@ -4628,84 +4639,8 @@ process_event_stop_test: /* In all-stop mode, if we're currently stepping but have stopped in some other thread, we need to switch back to the stepped thread. */ - if (!non_stop) - { - struct thread_info *tp; - - tp = iterate_over_threads (currently_stepping_or_nexting_callback, - ecs->event_thread); - if (tp) - { - /* However, if the current thread is blocked on some internal - breakpoint, and we simply need to step over that breakpoint - to get it going again, do that first. */ - if ((ecs->event_thread->control.trap_expected - && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_TRAP) - || ecs->event_thread->stepping_over_breakpoint) - { - keep_going (ecs); - return; - } - - /* If the stepping thread exited, then don't try to switch - back and resume it, which could fail in several different - ways depending on the target. Instead, just keep going. - - We can find a stepping dead thread in the thread list in - two cases: - - - The target supports thread exit events, and when the - target tries to delete the thread from the thread list, - inferior_ptid pointed at the exiting thread. In such - case, calling delete_thread does not really remove the - thread from the list; instead, the thread is left listed, - with 'exited' state. - - - The target's debug interface does not support thread - exit events, and so we have no idea whatsoever if the - previously stepping thread is still alive. For that - reason, we need to synchronously query the target - now. */ - if (is_exited (tp->ptid) - || !target_thread_alive (tp->ptid)) - { - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, - "infrun: not switching back to " - "stepped thread, it has vanished\n"); - - delete_thread (tp->ptid); - keep_going (ecs); - return; - } - - /* Otherwise, we no longer expect a trap in the current thread. - Clear the trap_expected flag before switching back -- this is - what keep_going would do as well, if we called it. */ - ecs->event_thread->control.trap_expected = 0; - - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, - "infrun: switching back to stepped thread\n"); - - ecs->event_thread = tp; - ecs->ptid = tp->ptid; - context_switch (ecs->ptid); - keep_going (ecs); - return; - } - } - - if (ecs->random_signal) - { - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, - "infrun: random signal, keep going\n"); - - /* Signal not stepping related. */ - keep_going (ecs); - return; - } + if (switch_back_to_stepped_thread (ecs)) + return; if (ecs->event_thread->control.step_resume_breakpoint) { @@ -5286,6 +5221,84 @@ process_event_stop_test: keep_going (ecs); } +/* In all-stop mode, if we're currently stepping but have stopped in + some other thread, we may need to switch back to the stepped + thread. Returns true we set the inferior running, false if we left + it stopped (and the event needs further processing). */ + +static int +switch_back_to_stepped_thread (struct execution_control_state *ecs) +{ + if (!non_stop) + { + struct thread_info *tp; + + tp = iterate_over_threads (currently_stepping_or_nexting_callback, + ecs->event_thread); + if (tp) + { + /* However, if the current thread is blocked on some internal + breakpoint, and we simply need to step over that breakpoint + to get it going again, do that first. */ + if ((ecs->event_thread->control.trap_expected + && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_TRAP) + || ecs->event_thread->stepping_over_breakpoint) + { + keep_going (ecs); + return 1; + } + + /* If the stepping thread exited, then don't try to switch + back and resume it, which could fail in several different + ways depending on the target. Instead, just keep going. + + We can find a stepping dead thread in the thread list in + two cases: + + - The target supports thread exit events, and when the + target tries to delete the thread from the thread list, + inferior_ptid pointed at the exiting thread. In such + case, calling delete_thread does not really remove the + thread from the list; instead, the thread is left listed, + with 'exited' state. + + - The target's debug interface does not support thread + exit events, and so we have no idea whatsoever if the + previously stepping thread is still alive. For that + reason, we need to synchronously query the target + now. */ + if (is_exited (tp->ptid) + || !target_thread_alive (tp->ptid)) + { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: not switching back to " + "stepped thread, it has vanished\n"); + + delete_thread (tp->ptid); + keep_going (ecs); + return 1; + } + + /* Otherwise, we no longer expect a trap in the current thread. + Clear the trap_expected flag before switching back -- this is + what keep_going would do as well, if we called it. */ + ecs->event_thread->control.trap_expected = 0; + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: switching back to stepped thread\n"); + + ecs->event_thread = tp; + ecs->ptid = tp->ptid; + context_switch (ecs->ptid); + keep_going (ecs); + return 1; + } + } + return 0; +} + /* Is thread TP in the middle of single-stepping? */ static int -- 2.39.5