From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20781 invoked by alias); 24 Feb 2012 22:21:47 -0000 Received: (qmail 20769 invoked by uid 22791); 24 Feb 2012 22:21:46 -0000 X-SWARE-Spam-Status: No, hits=-6.7 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 24 Feb 2012 22:21:29 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1OMLT0F027069 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 24 Feb 2012 17:21:29 -0500 Received: from hit-nxdomain.opendns.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q1OMLRL5013563 for ; Fri, 24 Feb 2012 17:21:28 -0500 Subject: [PATCH] PR server/9684: gdbserver, attach to stopped processes To: gdb-patches@sourceware.org From: Pedro Alves Date: Fri, 24 Feb 2012 23:00:00 -0000 Message-ID: <20120224222127.14659.51317.stgit@hit-nxdomain.opendns.com> User-Agent: StGit/0.15 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit 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: 2012-02/txt/msg00595.txt.bz2 This teaches GDBserver to attach to job control stopped processes 'T (stopped)', using the same trick GDB uses. Refs: http://sourceware.org/ml/gdb-patches/2008-04/msg00241.html http://sourceware.org/ml/gdb-patches/2008-04/msg00028.html http://sourceware.org/ml/gdb-patches/2007-06/msg00059.html This patch is simpler than linux-nat's equivalent patch was, given that GDBserver doesn't block waiting for lwps to report the attach stop. Instead all that is handled through the regular target_wait path. That and that linux-nat.c's state at the time of that patch was a little messy. :-) I'm a bit ambivalent on this. I found out that this isn't actually necessary on recent kernels (I haven't looked for the exact version or commit that made it so) -- waitpid no longer hangs. OTOH, we still need it on systems with not so recent kernels where support is still well active, so I figure this may be useful to many upstream as well. Note that once we have PTRACE_SEIZE support this hack will definitely be unnecessary, so it's likely that the window of kernels where this is actually unnecessary, but used, will be narrow-ish (assuming I or someone else gets to PTRACE_SEIZE in reasonable time). Tested with the extended-remote board on x86_64 Fedora 16 (3.2, doesn't need patch), and x86_64 RHEL 5.8 (2.6.18, needs patch). 2012-02-24 Pedro Alves PR server/9684 * linux-low.c (pid_is_stopped): New. (linux_attach_lwp_1): Handle attaching to 'T (stopped)' processes. --- 0 files changed, 0 insertions(+), 0 deletions(-) diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index ab34d84..11c53e6 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -598,6 +598,37 @@ linux_create_inferior (char *program, char **allargs) return pid; } +/* Detect `T (stopped)' in `/proc/PID/status'. + Other states including `T (tracing stop)' are reported as false. */ + +static int +pid_is_stopped (pid_t pid) +{ + FILE *status_file; + char buf[100]; + int retval = 0; + + snprintf (buf, sizeof (buf), "/proc/%d/status", (int) pid); + status_file = fopen (buf, "r"); + if (status_file != NULL) + { + int have_state = 0; + + while (fgets (buf, sizeof (buf), status_file)) + { + if (strncmp (buf, "State:", 6) == 0) + { + have_state = 1; + break; + } + } + if (have_state && strstr (buf, "T (stopped)") != NULL) + retval = 1; + fclose (status_file); + } + return retval; +} + /* Attach to an inferior process. */ static void @@ -643,6 +674,33 @@ linux_attach_lwp_1 (unsigned long lwpid, int initial) ptrace call on this LWP. */ new_lwp->must_set_ptrace_flags = 1; + if (pid_is_stopped (lwpid)) + { + if (debug_threads) + fprintf (stderr, + "Attached to a stopped process\n"); + + /* The process is definitely stopped. It is in a job control + stop, unless the kernel predates the TASK_STOPPED / + TASK_TRACED distinction, in which case it might be in a + ptrace stop. Make sure it is in a ptrace stop; from there we + can kill it, signal it, et cetera. + + First make sure there is a pending SIGSTOP. Since we are + already attached, the process can not transition from stopped + to running without a PTRACE_CONT; so we know this signal will + go into the queue. The SIGSTOP generated by PTRACE_ATTACH is + probably already in the queue (unless this kernel is old + enough to use TASK_STOPPED for ptrace stops); but since + SIGSTOP is not an RT signal, it can only be queued once. */ + kill_lwp (lwpid, SIGSTOP); + + /* Finally, resume the stopped process. This will deliver the + SIGSTOP (or a higher priority signal, just like normal + PTRACE_ATTACH), which we'll catch later on. */ + ptrace (PTRACE_CONT, lwpid, 0, 0); + } + /* The next time we wait for this LWP we'll see a SIGSTOP as PTRACE_ATTACH brings it to a halt.