From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10759 invoked by alias); 24 Jul 2015 18:05:44 -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 10750 invoked by uid 89); 24 Jul 2015 18:05:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL,BAYES_00,SPF_PASS autolearn=ham version=3.3.2 X-HELO: usevmg20.ericsson.net Received: from usevmg20.ericsson.net (HELO usevmg20.ericsson.net) (198.24.6.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 24 Jul 2015 18:05:40 +0000 Received: from EUSAAHC002.ericsson.se (Unknown_Domain [147.117.188.78]) by usevmg20.ericsson.net (Symantec Mail Security) with SMTP id 97.0A.12958.D6222B55; Fri, 24 Jul 2015 13:33:01 +0200 (CEST) Received: from [142.133.110.144] (147.117.188.8) by smtp-am.internal.ericsson.com (147.117.188.80) with Microsoft SMTP Server id 14.3.210.2; Fri, 24 Jul 2015 14:05:37 -0400 Message-ID: <55B27E71.1090705@ericsson.com> Date: Fri, 24 Jul 2015 18:05:00 -0000 From: Simon Marchi User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Pedro Alves , "Breazeal, Don" 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> In-Reply-To: <55B1308E.4020700@redhat.com> Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2015-07/txt/msg00708.txt.bz2 On 15-07-23 02:21 PM, Pedro Alves wrote: > So I managed to extract out this smaller patch from the > gdbserver fixes I mentioned. I think this one looks safe enough > for 7.10. WDYT? > > ----------- > From 98d41152bff2a21f7fda864d87ee5dd0cffa2d17 Mon Sep 17 00:00:00 2001 > From: Pedro Alves > Date: Thu, 23 Jul 2015 18:49:51 +0100 > Subject: [PATCH] remote follow fork and spurious child stops in non-stop mode > > Running gdb.threads/fork-plus-threads.exp against gdbserver in > extended-remote mode, even though the test passes, we still see broken > behavior: > > Running gdb.threads/fork-plus-threads.exp against gdbserver in > extended-remote mode, even though the test passes, we still see broken > behavior: > > (gdb) PASS: gdb.threads/fork-plus-threads.exp: set detach-on-fork off > continue & > Continuing. > (gdb) PASS: gdb.threads/fork-plus-threads.exp: continue & > [New Thread 28092.28092] > > [Thread 28092.28092] #2 stopped. > [New Thread 28094.28094] > [Inferior 2 (process 28092) exited normally] > [New Thread 28094.28105] > [New Thread 28094.28109] > > ... > > [Thread 28174.28174] #18 stopped. > [New Thread 28185.28185] > [Inferior 10 (process 28174) exited normally] > [New Thread 28185.28196] > > [Thread 28185.28185] #20 stopped. > Cannot remove breakpoints because program is no longer writable. > Further execution is probably impossible. > [Inferior 11 (process 28185) exited normally] > [Inferior 1 (process 28091) exited normally] > PASS: gdb.threads/fork-plus-threads.exp: reached breakpoint > info threads > No threads. > (gdb) PASS: gdb.threads/fork-plus-threads.exp: no threads left > info inferiors > Num Description Executable > * 1 /home/pedro/gdb/mygit/build/gdb/testsuite/gdb.threads/fork-plus-threads > (gdb) PASS: gdb.threads/fork-plus-threads.exp: only inferior 1 left > > All the "[Thread FOO] #NN stopped." above are bogus, as well as the > "Cannot remove breakpoints because program is no longer writable.", > which is a consequence. > > The problem is that when we intercept a fork event, we should report > the event for the parent, only, and leave the child stopped, but not > report its stop event. GDB later decides whether to follow the parent > or the child. But because handle_extended_wait does not set the > child's last_status.kind to TARGET_WAITKIND_STOPPED, a > stop_all_threads/unstop_all_lwps sequence (e.g., from trying to access > memory) by mistake ends up queueing a SIGSTOP on the child, resuming > it, and then when that SIGSTOP is intercepted, because the LWP has > last_resume_kind set to resume_stop, gdbserver reports the stop to > GDB, as GDB_SIGNAL_0: > > ... > >>>> entering unstop_all_lwps > unstopping all lwps > proceed_one_lwp: lwp 1600 > client wants LWP to remain 1600 stopped > proceed_one_lwp: lwp 1828 > Client wants LWP 1828 to stop. Making sure it has a SIGSTOP pending > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > Sending sigstop to lwp 1828 > pc is 0x3615ebc7cc > Resuming lwp 1828 (continue, signal 0, stop expected) > continue from pc 0x3615ebc7cc > unstop_all_lwps done > sigchld_handler > <<<< exiting unstop_all_lwps > handling possible target event > >>>> entering linux_wait_1 > linux_wait_1: [] > my_waitpid (-1, 0x40000001) > my_waitpid (-1, 0x1): status(137f), 1828 > LWFE: waitpid(-1, ...) returned 1828, ERRNO-OK > LLW: waitpid 1828 received Stopped (signal) (stopped) > pc is 0x3615ebc7cc > Expected stop. > LLW: resume_stop SIGSTOP caught for LWP 1828.1828. > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > ... > linux_wait_1 ret = LWP 1828.1828, 1, 0 > <<<< exiting linux_wait_1 > Writing resume reply for LWP 1828.1828:1 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > By inspection, I also noticed that we miss leaving the child with the > suspend count incremented if stopping threads, like we do for clone > threads. > > Tested on x86_64 Fedora 20, extended-remote. > > gdb/gdbserver/ChangeLog: > 2015-07-23 Pedro Alves > > * linux-low.c (handle_extended_wait): Set the child's last > reported status to TARGET_WAITKIND_STOPPED. > --- > gdb/gdbserver/linux-low.c | 7 ++++++ > gdb/testsuite/gdb.threads/fork-plus-threads.exp | 30 +++++++++++++++++++++++++ > 2 files changed, 37 insertions(+) > > diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c > 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; > + > + /* If we're suspending all threads, leave this one suspended > + too. */ > + if (stopping_threads == STOPPING_AND_SUSPENDING_THREADS) > + child_lwp->suspended = 1; > + > parent_proc = get_thread_process (event_thr); > child_proc->attached = parent_proc->attached; > clone_all_breakpoints (&child_proc->breakpoints, > diff --git a/gdb/testsuite/gdb.threads/fork-plus-threads.exp b/gdb/testsuite/gdb.threads/fork-plus-threads.exp > index f44dd76..80d2464 100644 > --- a/gdb/testsuite/gdb.threads/fork-plus-threads.exp > +++ b/gdb/testsuite/gdb.threads/fork-plus-threads.exp > @@ -48,13 +48,43 @@ gdb_test_multiple $test $test { > } > } > > +# gdbserver had a bug that resulted in reporting the fork child's > +# initial stop to gdb, which gdb does not expect, in turn resulting in > +# a broken session, like: > +# > +# [Thread 31536.31536] #16 stopped. <== BAD > +# [New Thread 31547.31547] > +# [Inferior 10 (process 31536) exited normally] > +# [New Thread 31547.31560] > +# > +# [Thread 31547.31547] #18 stopped. <== BAD > +# Cannot remove breakpoints because program is no longer writable. <== BAD > +# Further execution is probably impossible. <== BAD > +# [Inferior 11 (process 31547) exited normally] > +# [Inferior 1 (process 31454) exited normally] > +# > +# These variables track whether we see such broken behavior. > +set saw_cannot_remove_breakpoints 0 > +set saw_thread_stopped 0 > + > set test "reached breakpoint" > 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 > } > } > > +gdb_assert !$saw_cannot_remove_breakpoints "no failure to remove breakpoints" > +gdb_assert !$saw_thread_stopped "no spurious thread stop" > + > gdb_test "info threads" "No threads\." \ > "no threads left" I tried it and it works as expected. If you try the same test program in all-stop though, fork childs are left stopped. Is it expected? I am not sure how forking interacts with all-stop. ----------------------- $ ./gdb -q -nx -ex "set detach-on-fork off" testsuite/gdb.threads/fork-plus-threads Reading symbols from testsuite/gdb.threads/fork-plus-threads...done. (gdb) r & Starting program: /home/emaisin/src/binutils-gdb/gdb/testsuite/gdb.threads/fork-plus-threads (gdb) [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5304] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5305] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5306] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5307] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5308] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5309] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5310] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5311] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5312] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [New process 5313] [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". i th Id Target Id Frame 11 process 5313 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 10 process 5312 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 9 process 5311 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 8 process 5310 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 7 process 5309 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 6 process 5308 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 5 process 5307 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 4 process 5306 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 3 process 5305 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 2 process 5304 "fork-plus-threa" 0x00007ffff78b8025 in fork () from /lib/x86_64-linux-gnu/libc.so.6 * 1 Thread 0x7ffff7fc9740 (LWP 5300) "fork-plus-threa" (running)