2008-04-12 Pedro Alves * linux-nat.c (get_pending_status): New. (detach_callback): Pass pending signal. (linux_nat_detach): Pass pending signal. --- gdb/linux-nat.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) Index: src/gdb/linux-nat.c =================================================================== --- src.orig/gdb/linux-nat.c 2008-04-12 16:20:27.000000000 +0100 +++ src/gdb/linux-nat.c 2008-04-12 17:36:54.000000000 +0100 @@ -1289,6 +1289,36 @@ linux_nat_attach (char *args, int from_t } } +/* Get pending status of LP. */ +static int +get_pending_status (struct lwp_info *lp, int *status) +{ + struct target_waitstatus last; + ptid_t last_ptid; + + get_last_target_status (&last_ptid, &last); + + /* If this lwp is the ptid that GDB is processing an event from, the + signal will be in stop_signal. Otherwise, in all-stop + sync + mode, we may cache pending events in lp->status while trying to + stop all threads (see stop_wait_callback). In async mode, the + events are always cached in waitpid_queue. */ + + *status = 0; + if (GET_LWP (lp->ptid) == GET_LWP (last_ptid)) + { + if (stop_signal != TARGET_SIGNAL_0 + && signal_pass_state (stop_signal)) + *status = W_STOPCODE (target_signal_to_host (stop_signal)); + } + else if (target_can_async_p ()) + queued_waitpid (GET_LWP (lp->ptid), status, __WALL); + else + *status = lp->status; + + return 0; +} + static int detach_callback (struct lwp_info *lp, void *data) { @@ -1311,18 +1341,18 @@ detach_callback (struct lwp_info *lp, vo lp->signalled = 0; } - /* Pass on the last signal, if appropriate. */ - if (lp->status == 0 && GET_LWP (lp->ptid) == GET_LWP (inferior_ptid) - && stop_signal != TARGET_SIGNAL_0 && signal_pass_state (stop_signal)) - lp->status = W_STOPCODE (target_signal_to_host (stop_signal)); - /* We don't actually detach from the LWP that has an id equal to the overall process id just yet. */ if (GET_LWP (lp->ptid) != GET_PID (lp->ptid)) { + int status = 0; + + /* Pass on any pending signal for this LWP. */ + get_pending_status (lwp_list, &status); + errno = 0; if (ptrace (PTRACE_DETACH, GET_LWP (lp->ptid), 0, - WSTOPSIG (lp->status)) < 0) + WSTOPSIG (status)) < 0) error (_("Can't detach %s: %s"), target_pid_to_str (lp->ptid), safe_strerror (errno)); @@ -1332,7 +1362,6 @@ detach_callback (struct lwp_info *lp, vo target_pid_to_str (lp->ptid), strsignal (WSTOPSIG (lp->status))); - drain_queued_events (GET_LWP (lp->ptid)); delete_lwp (lp->ptid); } @@ -1349,14 +1378,15 @@ linux_nat_detach (char *args, int from_t if (target_can_async_p ()) linux_nat_async (NULL, 0); - iterate_over_lwps (detach_callback, &status); + iterate_over_lwps (detach_callback, NULL); /* Only the initial process should be left right now. */ gdb_assert (num_lwps == 1); /* Pass on any pending signal for the last LWP. */ - status = lwp_list->status; - if (WIFSTOPPED (status) && (args == NULL || *args == '\0')) + if ((args == NULL || *args == '\0') + && get_pending_status (lwp_list, &status) != -1 + && WIFSTOPPED (status)) { args = alloca (8); sprintf (args, "%d", (int) WSTOPSIG (status));