From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15921 invoked by alias); 29 Jul 2015 13:21:25 -0000 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 Received: (qmail 15911 invoked by uid 89); 29 Jul 2015 13:21:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL,BAYES_00,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 29 Jul 2015 13:21:23 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id F25258E51D; Wed, 29 Jul 2015 13:21:21 +0000 (UTC) Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6TDLJd9016943; Wed, 29 Jul 2015 09:21:20 -0400 Message-ID: <55B8D34F.5060002@redhat.com> Date: Wed, 29 Jul 2015 13:21:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: Don Breazeal , "Breazeal, Don" , Simon Marchi CC: GDB Patches Subject: Re: [PATCH 3/N] remote follow fork and spurious child stops in non-stop mode References: <1437672294-29351-1-git-send-email-palves@redhat.com> <55B1308E.4020700@redhat.com> <55B2875E.1070504@codesourcery.com> In-Reply-To: <55B2875E.1070504@codesourcery.com> Content-Type: multipart/mixed; boundary="------------040209000003050704070206" X-SW-Source: 2015-07/txt/msg00868.txt.bz2 This is a multi-part message in MIME format. --------------040209000003050704070206 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Content-length: 4061 Hi Don, Sorry for the delay. On 07/24/2015 07:43 PM, Don Breazeal wrote: >> index 17b2a51..56a33ff 100644 >> --- a/gdb/gdbserver/linux-low.c >> +++ b/gdb/gdbserver/linux-low.c >> @@ -488,6 +488,13 @@ handle_extended_wait (struct lwp_info *event_lwp, int wstat) >> child_lwp->status_pending_p = 0; >> child_thr = get_lwp_thread (child_lwp); >> child_thr->last_resume_kind = resume_stop; >> + child_thr->last_status.kind = TARGET_WAITKIND_STOPPED; > > This makes perfect sense to me. > Great. >> + >> + /* If we're suspending all threads, leave this one suspended >> + too. */ >> + if (stopping_threads == STOPPING_AND_SUSPENDING_THREADS) >> + child_lwp->suspended = 1; > > I have a question about this. In the definition of struct lwp_info in > linux-low.h, it has this comment: > > /* When this is true, we shall not try to resume this thread, even > if last_resume_kind isn't resume_stop. */ > int suspended; > > Since we are setting last_resume_kind to resume_stop here, is this > unnecessary? We still need it, because otherwise we'd decrement the suspend count below 0: static int unsuspend_and_proceed_one_lwp (struct inferior_list_entry *entry, void *except) { struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lwp = get_thread_lwp (thread); if (lwp == except) return 0; lwp->suspended--; gdb_assert (lwp->suspended >= 0); return proceed_one_lwp (entry, except); } It's proceed_one_lwp that skips resuming if the client wants the lwp stopped: static int proceed_one_lwp (struct inferior_list_entry *entry, void *except) { ... if (thread->last_resume_kind == resume_stop && thread->last_status.kind != TARGET_WAITKIND_IGNORE) { if (debug_threads) debug_printf (" client wants LWP to remain %ld stopped\n", lwpid_of (thread)); return 0; } I tried writing a test for this, by making a multithreaded program have all its threads but the main continuously fork (see attached), while the main thread continuously steps over a breakpoint (a conditional breakpoint with condition "0" should do it, as gdbserver handles that breakpoint itself), but that stumbles on yet more problems... :-/ $ ./gdb ./testsuite/gdb.threads/fork-plus-threads-2 -ex "set non-stop on" -ex "set detach-on-fork off" -ex "tar extended-rem :9999" ... Remote debugging using :9999 (gdb) [Thread 24971.24971] #1 stopped. 0x0000003615a011f0 in ?? () c& Continuing. (gdb) [New Thread 24971.24981] [New Thread 24983.24983] [New Thread 24971.24982] [Thread 24983.24983] #3 stopped. 0x0000003615ebc7cc in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130 130 pid = ARCH_FORK (); [New Thread 24984.24984] Error in re-setting breakpoint -16: PC register is not available Error in re-setting breakpoint -17: PC register is not available Error in re-setting breakpoint -18: PC register is not available Error in re-setting breakpoint -19: PC register is not available Error in re-setting breakpoint -24: PC register is not available Error in re-setting breakpoint -25: PC register is not available Error in re-setting breakpoint -26: PC register is not available Error in re-setting breakpoint -27: PC register is not available Error in re-setting breakpoint -28: PC register is not available Error in re-setting breakpoint -29: PC register is not available Error in re-setting breakpoint -30: PC register is not available PC register is not available (gdb) >> set test "reached breakpoint" BTW, I noticed that this test message is stale from my previous attempt at running to a breakpoint instead of to exit. I changed it to: set test "inferior 1 exited" in patch 1/2. >> gdb_test_multiple "" $test { >> + -re "Cannot remove breakpoints" { >> + set saw_cannot_remove_breakpoints 1 >> + exp_continue >> + } >> + -re "Thread \[^\r\n\]+ stopped\\." { >> + set saw_thread_stopped 1 >> + exp_continue >> + } >> -re "Inferior 1 \(\[^\r\n\]+\) exited normally" { >> pass $test >> } >> } Thanks, Pedro Alves --------------040209000003050704070206 Content-Type: text/plain; charset=UTF-8; name="fork-plus-threads-2.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="fork-plus-threads-2.c" Content-length: 2029 /* This testcase is part of GDB, the GNU debugger. Copyright 2015 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include /* Number of threads. Each thread continuously spawns a fork and wait for it. If we have another thread continuously start a step over, gdbserver should end up finding new forks while suspending threads. */ #define NTHREADS 10 pthread_t threads[NTHREADS]; static void * thread_func (void *arg) { while (1) { pid_t pid; pid = fork (); if (pid > 0) { int status; /* Parent. */ pid = waitpid (pid, &status, 0); if (pid == -1) { perror ("wait"); exit (1); } if (!WIFEXITED (status)) { printf ("Unexpected wait status 0x%x from child %d\n", status, pid); } } else if (pid == 0) { /* Child. */ exit (0); } else { perror ("fork"); exit (1); } } } int main (void) { int i; int ret; for (i = 0; i < NTHREADS; i++) { ret = pthread_create (&threads[i], NULL, thread_func, NULL); assert (ret == 0); } for (i = 0; i < NTHREADS; i++) { ret = pthread_join (threads[i], NULL); assert (ret == 0); } /* Don't run forever. */ sleep (180); return 0; } --------------040209000003050704070206--