aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <pedro@palves.net>2021-01-11 23:11:57 +0000
committerPedro Alves <pedro@palves.net>2021-01-13 01:07:13 +0000
commit48749858473823d2fbabbe9594c8196e3c812bb4 (patch)
tree50dbd5cbd78b27eaab8f0e786c4e028c5daef322
parentbae1a66b1d36569dfa61645bac09fbb785d89d6f (diff)
downloadbinutils-48749858473823d2fbabbe9594c8196e3c812bb4.zip
binutils-48749858473823d2fbabbe9594c8196e3c812bb4.tar.gz
binutils-48749858473823d2fbabbe9594c8196e3c812bb4.tar.bz2
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.
-rw-r--r--gdb/infrun.c45
1 files changed, 41 insertions, 4 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 12e1564..4a17410 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1261,15 +1261,15 @@ struct step_over_info
and address of the instruction the breakpoint is set at. We'll
skip inserting all breakpoints here. Valid iff ASPACE is
non-NULL. */
- const address_space *aspace;
- CORE_ADDR address;
+ const address_space *aspace = nullptr;
+ CORE_ADDR address = 0;
/* The instruction being stepped over triggers a nonsteppable
watchpoint. If true, we'll skip inserting watchpoints. */
- int nonsteppable_watchpoint_p;
+ int nonsteppable_watchpoint_p = 0;
/* The thread's global number. */
- int thread;
+ int thread = -1;
};
/* 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 void restart_threads (struct thread_info *event_thread);
/* Prepare and stabilize the inferior for detaching it. E.g.,
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);
}
+ /* 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))
{
infrun_debug_printf ("displaced-stepping in-process while detaching");
@@ -5526,6 +5556,13 @@ restart_threads (struct thread_info *event_thread)
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);
if (tp == event_thread)