aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2013-10-28 16:39:05 +0000
committerPedro Alves <palves@redhat.com>2013-10-28 16:45:02 +0000
commitc447ac0bfb51568d4c239dd11e016dc0281ee358 (patch)
tree636aff84ed518729f7b4336ab54bf8f4a45ed8ab /gdb/infrun.c
parentf05e4c1115dec06d408394e2d9a529d1475f96ee (diff)
downloadfsf-binutils-gdb-c447ac0bfb51568d4c239dd11e016dc0281ee358.zip
fsf-binutils-gdb-c447ac0bfb51568d4c239dd11e016dc0281ee358.tar.gz
fsf-binutils-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.c169
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