From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4496 invoked by alias); 12 Apr 2008 16:38:15 -0000 Received: (qmail 4485 invoked by uid 22791); 12 Apr 2008 16:38:14 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 12 Apr 2008 16:37:53 +0000 Received: (qmail 23549 invoked from network); 12 Apr 2008 16:37:51 -0000 Received: from unknown (HELO orlando.local) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 12 Apr 2008 16:37:51 -0000 From: Pedro Alves To: gdb-patches@sourceware.org Subject: Re: [patch] Fix Linux attach to signalled/stopped processes Date: Sun, 13 Apr 2008 09:35:00 -0000 User-Agent: KMail/1.9.6 (enterprise 0.20070907.709405) Cc: Daniel Jacobowitz , Roland McGrath , Jan Kratochvil , Doug Evans , mark.kettenis@xs4all.nl References: <200804112354.49254.pedro@codesourcery.com> <200804120021.34444.pedro@codesourcery.com> In-Reply-To: <200804120021.34444.pedro@codesourcery.com> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_dVOAIwZ6+IRC6Gc" Message-Id: <200804121737.49116.pedro@codesourcery.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-04/txt/msg00236.txt.bz2 --Boundary-00=_dVOAIwZ6+IRC6Gc Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Content-length: 806 A Saturday 12 April 2008 00:21:33, Pedro Alves wrote: > A Friday 11 April 2008 23:54:48, Pedro Alves wrote: > > A Friday 11 April 2008 23:19:58, Daniel Jacobowitz wrote: > > > Any idea how to do this? > > > Actually, get_last_target_status should give you the ptid > you want, I think. Like so ? The only way I could find to pass args != NULL, was to attach, and then "quit $signo". "detach $SIGNO" doesn't work: (gdb) detach 21 Undefined detach command: "21". Try "help detach". -- and was glad it didn't. I'm was hoping we can use "detach $pid" in the future, to mirror "attach $pid", but now I'm not sure we can... Anyway, "q 19" did send a SIGSTOP, and the process was stopped. And I was able to attach to stopped processes, and the new tests passed, which is nice. Hurray! -- Pedro Alves --Boundary-00=_dVOAIwZ6+IRC6Gc Content-Type: text/x-diff; charset="iso-8859-1"; name="attach_stopped_pend_sig.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="attach_stopped_pend_sig.diff" Content-length: 3404 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)); --Boundary-00=_dVOAIwZ6+IRC6Gc--