detach with in-line step over in progress

A following patch will add a testcase that has a number of threads
constantly stepping over a breakpoint, and then has GDB detach the
process.  That testcase exercises both "set displaced-stepping
on/off".  Testing with "set displaced-stepping off" reveals that GDB
does not handle the case of the user typing "detach" just while some
thread is in the middle of an in-line step over.  If that thread
belongs to the inferior that is being detached, then the step-over
never finishes, and threads of other inferiors are never re-resumed.
This fixes it.

gdb/ChangeLog:

	* infrun.c (struct step_over_info): Initialize fields.
	(prepare_for_detach): Handle ongoing in-line step over.
This commit is contained in:
Pedro Alves
2021-01-11 23:11:57 +00:00
parent e87f0fe823
commit ac7d717c1e
2 changed files with 46 additions and 4 deletions

View File

@ -1,3 +1,8 @@
2021-02-03 Pedro Alves <pedro@palves.net>
* infrun.c (struct step_over_info): Initialize fields.
(prepare_for_detach): Handle ongoing in-line step over.
2021-02-03 Pedro Alves <pedro@palves.net> 2021-02-03 Pedro Alves <pedro@palves.net>
* linux-nat.c (linux_nat_target::detach): Remove breakpoints * linux-nat.c (linux_nat_target::detach): Remove breakpoints

View File

@ -1261,15 +1261,15 @@ struct step_over_info
and address of the instruction the breakpoint is set at. We'll and address of the instruction the breakpoint is set at. We'll
skip inserting all breakpoints here. Valid iff ASPACE is skip inserting all breakpoints here. Valid iff ASPACE is
non-NULL. */ non-NULL. */
const address_space *aspace; const address_space *aspace = nullptr;
CORE_ADDR address; CORE_ADDR address = 0;
/* The instruction being stepped over triggers a nonsteppable /* The instruction being stepped over triggers a nonsteppable
watchpoint. If true, we'll skip inserting watchpoints. */ watchpoint. If true, we'll skip inserting watchpoints. */
int nonsteppable_watchpoint_p; int nonsteppable_watchpoint_p = 0;
/* The thread's global number. */ /* The thread's global number. */
int thread; int thread = -1;
}; };
/* The step-over info of the location that is being stepped over. /* The step-over info of the location that is being stepped over.
@ -3566,6 +3566,7 @@ struct wait_one_event
}; };
static bool handle_one (const wait_one_event &event); static bool handle_one (const wait_one_event &event);
static void restart_threads (struct thread_info *event_thread);
/* Prepare and stabilize the inferior for detaching it. E.g., /* Prepare and stabilize the inferior for detaching it. E.g.,
detaching while a thread is displaced stepping is a recipe for detaching while a thread is displaced stepping is a recipe for
@ -3593,6 +3594,35 @@ prepare_for_detach (void)
global_thread_step_over_chain_remove (tp); global_thread_step_over_chain_remove (tp);
} }
/* If we were already in the middle of an inline step-over, and the
thread stepping belongs to the inferior we're detaching, we need
to restart the threads of other inferiors. */
if (step_over_info.thread != -1)
{
infrun_debug_printf ("inline step-over in-process while detaching");
thread_info *thr = find_thread_global_id (step_over_info.thread);
if (thr->inf == inf)
{
/* Since we removed threads of INF from the step-over chain,
we know this won't start a step-over for INF. */
clear_step_over_info ();
if (target_is_non_stop_p ())
{
/* Start a new step-over in another thread if there's
one that needs it. */
start_step_over ();
/* Restart all other threads (except the
previously-stepping thread, since that one is still
running). */
if (!step_over_info_valid_p ())
restart_threads (thr);
}
}
}
if (displaced_step_in_progress (inf)) if (displaced_step_in_progress (inf))
{ {
infrun_debug_printf ("displaced-stepping in-process while detaching"); infrun_debug_printf ("displaced-stepping in-process while detaching");
@ -5528,6 +5558,13 @@ restart_threads (struct thread_info *event_thread)
for (thread_info *tp : all_non_exited_threads ()) for (thread_info *tp : all_non_exited_threads ())
{ {
if (tp->inf->detaching)
{
infrun_debug_printf ("restart threads: [%s] inferior detaching",
target_pid_to_str (tp->ptid).c_str ());
continue;
}
switch_to_thread_no_regs (tp); switch_to_thread_no_regs (tp);
if (tp == event_thread) if (tp == event_thread)