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.
This commit is contained in:
parent
f05e4c1115
commit
c447ac0bfb
|
@ -1,3 +1,12 @@
|
||||||
|
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.
|
||||||
|
|
||||||
2013-10-28 Pedro Alves <palves@redhat.com>
|
2013-10-28 Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
* infrun.c (clear_stop_func): Delete.
|
* infrun.c (clear_stop_func): Delete.
|
||||||
|
|
169
gdb/infrun.c
169
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 stop_stepping (struct execution_control_state *ecs);
|
||||||
static void prepare_to_wait (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 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
|
/* Callback for iterate over threads. If the thread is stopped, but
|
||||||
the user/frontend doesn't know about that yet, go through
|
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
|
(leaving the inferior at the step-resume-breakpoint without
|
||||||
actually executing it). Either way continue until the
|
actually executing it). Either way continue until the
|
||||||
breakpoint is really hit. */
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -4628,84 +4639,8 @@ process_event_stop_test:
|
||||||
|
|
||||||
/* In all-stop mode, if we're currently stepping but have stopped in
|
/* 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. */
|
some other thread, we need to switch back to the stepped thread. */
|
||||||
if (!non_stop)
|
if (switch_back_to_stepped_thread (ecs))
|
||||||
{
|
return;
|
||||||
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 (ecs->event_thread->control.step_resume_breakpoint)
|
if (ecs->event_thread->control.step_resume_breakpoint)
|
||||||
{
|
{
|
||||||
|
@ -5286,6 +5221,84 @@ process_event_stop_test:
|
||||||
keep_going (ecs);
|
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? */
|
/* Is thread TP in the middle of single-stepping? */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue