diff options
author | Pedro Alves <palves@redhat.com> | 2013-10-28 16:39:05 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2013-10-28 16:45:02 +0000 |
commit | c447ac0bfb51568d4c239dd11e016dc0281ee358 (patch) | |
tree | 636aff84ed518729f7b4336ab54bf8f4a45ed8ab /gdb/infrun.c | |
parent | f05e4c1115dec06d408394e2d9a529d1475f96ee (diff) | |
download | gdb-c447ac0bfb51568d4c239dd11e016dc0281ee358.zip gdb-c447ac0bfb51568d4c239dd11e016dc0281ee358.tar.gz gdb-c447ac0bfb51568d4c239dd11e016dc0281ee358.tar.bz2 |
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 <palves@redhat.com>
* 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.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 169 |
1 files changed, 91 insertions, 78 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 8b1b668..0da90ec 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 |