diff options
author | Pedro Alves <pedro@palves.net> | 2021-01-11 23:11:57 +0000 |
---|---|---|
committer | Pedro Alves <pedro@palves.net> | 2021-01-13 01:07:13 +0000 |
commit | 48749858473823d2fbabbe9594c8196e3c812bb4 (patch) | |
tree | 50dbd5cbd78b27eaab8f0e786c4e028c5daef322 | |
parent | bae1a66b1d36569dfa61645bac09fbb785d89d6f (diff) | |
download | binutils-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.c | 45 |
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) |