diff options
author | Pedro Alves <palves@redhat.com> | 2009-05-28 17:19:58 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2009-05-28 17:19:58 +0000 |
commit | b3444185bd700fa4e5cea80a10298cf8d16bcbce (patch) | |
tree | 1330f456627b45848d64ce310201f76b3b4c7628 /gdb/infrun.c | |
parent | 8f5008704e9f9e282da288b71fefb96e889ea961 (diff) | |
download | gdb-b3444185bd700fa4e5cea80a10298cf8d16bcbce.zip gdb-b3444185bd700fa4e5cea80a10298cf8d16bcbce.tar.gz gdb-b3444185bd700fa4e5cea80a10298cf8d16bcbce.tar.bz2 |
gdb/
2009-05-28 Pedro Alves <pedro@codesourcery.com>
* infrun.c (handle_inferior_event): When thread hoping, switch
inferior_ptid to the event thread before removing breakpoints from
the target. If not stopping, also try to revert back to a thread
that was doing a "next". Check if that thread still exists before
resuming.
(currently_stepping_thread): Delete and merge with ...
(currently_stepping): ... this.
(currently_stepping_callback): Rename to ...
(currently_stepping_or_nexting_callback): ... this, and also
return true if the thread was stepping over a call (has a
step-resume breakpoint).
gdb/testsuite/
2009-05-28 Pedro Alves <pedro@codesourcery.com>
* gdb.threads/threxit-hop-specific.c: New.
* gdb.threads/threxit-hop-specific.exp: New.
* gdb.threads/thread-execl.c: New.
* gdb.threads/thread-execl.exp: New.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r-- | gdb/infrun.c | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 381d208..88a1c4e 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -75,7 +75,8 @@ static void set_schedlock_func (char *args, int from_tty, static int currently_stepping (struct thread_info *tp); -static int currently_stepping_callback (struct thread_info *tp, void *data); +static int currently_stepping_or_nexting_callback (struct thread_info *tp, + void *data); static void xdb_handle_command (char *args, int from_tty); @@ -2896,6 +2897,11 @@ targets should add new threads to the thread list themselves in non-stop mode.") if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: thread_hop_needed\n"); + /* Switch context before touching inferior memory, the + previous thread may have exited. */ + if (!ptid_equal (inferior_ptid, ecs->ptid)) + context_switch (ecs->ptid); + /* Saw a breakpoint, but it was hit by the wrong thread. Just continue. */ @@ -2922,9 +2928,6 @@ targets should add new threads to the thread list themselves in non-stop mode.") error (_("Cannot step over breakpoint hit in wrong thread")); else { /* Single step */ - if (!ptid_equal (inferior_ptid, ecs->ptid)) - context_switch (ecs->ptid); - if (!non_stop) { /* Only need to require the next event from this @@ -3483,7 +3486,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); if (!non_stop) { struct thread_info *tp; - tp = iterate_over_threads (currently_stepping_callback, + tp = iterate_over_threads (currently_stepping_or_nexting_callback, ecs->event_thread); if (tp) { @@ -3498,6 +3501,21 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); return; } + /* If the stepping thread exited, then don't try reverting + back to it, just keep going. We need to query the target + in case it doesn't support thread exit events. */ + 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. */ @@ -3931,28 +3949,29 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); keep_going (ecs); } -/* Are we in the middle of stepping? */ +/* Is thread TP in the middle of single-stepping? */ static int -currently_stepping_thread (struct thread_info *tp) +currently_stepping (struct thread_info *tp) { - return (tp->step_range_end && tp->step_resume_breakpoint == NULL) - || tp->trap_expected - || tp->stepping_through_solib_after_catch; + return ((tp->step_range_end && tp->step_resume_breakpoint == NULL) + || tp->trap_expected + || tp->stepping_through_solib_after_catch + || bpstat_should_step ()); } -static int -currently_stepping_callback (struct thread_info *tp, void *data) -{ - /* Return true if any thread *but* the one passed in "data" is - in the middle of stepping. */ - return tp != data && currently_stepping_thread (tp); -} +/* Returns true if any thread *but* the one passed in "data" is in the + middle of stepping or of handling a "next". */ static int -currently_stepping (struct thread_info *tp) +currently_stepping_or_nexting_callback (struct thread_info *tp, void *data) { - return currently_stepping_thread (tp) || bpstat_should_step (); + if (tp == data) + return 0; + + return (tp->step_range_end + || tp->trap_expected + || tp->stepping_through_solib_after_catch); } /* Inferior has stepped into a subroutine call with source code that |