diff options
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r-- | gdb/gdbserver/linux-low.c | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 82fb7f9bb25..4cdedb4e661 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -264,6 +264,7 @@ static int linux_wait_for_event (ptid_t ptid, int *wstat, int options); static struct lwp_info *add_lwp (ptid_t ptid); static int linux_stopped_by_watchpoint (void); static void mark_lwp_dead (struct lwp_info *lwp, int wstat); +static int lwp_is_marked_dead (struct lwp_info *lwp); static void proceed_all_lwps (void); static int finish_step_over (struct lwp_info *lwp); static int kill_lwp (unsigned long lwpid, int signo); @@ -743,8 +744,9 @@ add_lwp (ptid_t ptid) { struct lwp_info *lwp; - lwp = (struct lwp_info *) xmalloc (sizeof (*lwp)); - memset (lwp, 0, sizeof (*lwp)); + lwp = (struct lwp_info *) xcalloc (1, sizeof (*lwp)); + + lwp->waitstatus.kind = TARGET_WAITKIND_IGNORE; if (the_low_target.new_thread != NULL) the_low_target.new_thread (lwp); @@ -1393,7 +1395,7 @@ linux_thread_alive (ptid_t ptid) exited but we still haven't been able to report it to GDB, we'll hold on to the last lwp of the dead process. */ if (lwp != NULL) - return !lwp->dead; + return !lwp_is_marked_dead (lwp); else return 0; } @@ -2747,20 +2749,6 @@ ignore_event (struct target_waitstatus *ourstatus) return null_ptid; } -/* Return non-zero if WAITSTATUS reflects an extended linux - event. Otherwise, return zero. */ - -static int -extended_event_reported (const struct target_waitstatus *waitstatus) -{ - if (waitstatus == NULL) - return 0; - - return (waitstatus->kind == TARGET_WAITKIND_FORKED - || waitstatus->kind == TARGET_WAITKIND_VFORKED - || waitstatus->kind == TARGET_WAITKIND_VFORK_DONE); -} - /* Wait for process, returns status. */ static ptid_t @@ -3128,7 +3116,7 @@ linux_wait_1 (ptid_t ptid, || (gdb_breakpoint_here (event_child->stop_pc) && gdb_condition_true_at_breakpoint (event_child->stop_pc) && gdb_no_commands_at_breakpoint (event_child->stop_pc)) - || extended_event_reported (&event_child->waitstatus)); + || event_child->waitstatus.kind != TARGET_WAITKIND_IGNORE); run_breakpoint_commands (event_child->stop_pc); @@ -3150,9 +3138,11 @@ linux_wait_1 (ptid_t ptid, paddress (event_child->stop_pc), paddress (event_child->step_range_start), paddress (event_child->step_range_end)); - if (extended_event_reported (&event_child->waitstatus)) + if (event_child->waitstatus.kind != TARGET_WAITKIND_IGNORE) { - char *str = target_waitstatus_to_string (ourstatus); + char *str; + + str = target_waitstatus_to_string (&event_child->waitstatus); debug_printf ("LWP %ld: extended event with waitstatus %s\n", lwpid_of (get_lwp_thread (event_child)), str); xfree (str); @@ -3266,12 +3256,11 @@ linux_wait_1 (ptid_t ptid, unstop_all_lwps (1, event_child); } - if (extended_event_reported (&event_child->waitstatus)) + if (event_child->waitstatus.kind != TARGET_WAITKIND_IGNORE) { - /* If the reported event is a fork, vfork or exec, let GDB know. */ - ourstatus->kind = event_child->waitstatus.kind; - ourstatus->value = event_child->waitstatus.value; - + /* If the reported event is an exit, fork, vfork or exec, let + GDB know. */ + *ourstatus = event_child->waitstatus; /* Clear the event lwp's waitstatus since we handled it already. */ event_child->waitstatus.kind = TARGET_WAITKIND_IGNORE; } @@ -3479,13 +3468,23 @@ suspend_and_send_sigstop_callback (struct inferior_list_entry *entry, static void mark_lwp_dead (struct lwp_info *lwp, int wstat) { - /* It's dead, really. */ - lwp->dead = 1; - /* Store the exit status for later. */ lwp->status_pending_p = 1; lwp->status_pending = wstat; + /* Store in waitstatus as well, as there's nothing else to process + for this event. */ + if (WIFEXITED (wstat)) + { + lwp->waitstatus.kind = TARGET_WAITKIND_EXITED; + lwp->waitstatus.value.integer = WEXITSTATUS (wstat); + } + else if (WIFSIGNALED (wstat)) + { + lwp->waitstatus.kind = TARGET_WAITKIND_SIGNALLED; + lwp->waitstatus.value.sig = gdb_signal_from_host (WTERMSIG (wstat)); + } + /* Prevent trying to stop it. */ lwp->stopped = 1; @@ -3493,6 +3492,17 @@ mark_lwp_dead (struct lwp_info *lwp, int wstat) lwp->stop_expected = 0; } +/* Return true if LWP has exited already, and has a pending exit event + to report to GDB. */ + +static int +lwp_is_marked_dead (struct lwp_info *lwp) +{ + return (lwp->status_pending_p + && (WIFEXITED (lwp->status_pending) + || WIFSIGNALED (lwp->status_pending))); +} + /* Wait for all children to stop for the SIGSTOPs we just queued. */ static void @@ -3609,7 +3619,7 @@ lwp_running (struct inferior_list_entry *entry, void *data) struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lwp = get_thread_lwp (thread); - if (lwp->dead) + if (lwp_is_marked_dead (lwp)) return 0; if (lwp->stopped) return 0; |