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:
Pedro Alves 2013-10-28 16:39:05 +00:00
parent f05e4c1115
commit c447ac0bfb
2 changed files with 100 additions and 78 deletions

View File

@ -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>
* infrun.c (clear_stop_func): Delete.

View File

@ -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