From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19331 invoked by alias); 4 Apr 2012 19:14:53 -0000 Received: (qmail 19320 invoked by uid 22791); 4 Apr 2012 19:14:50 -0000 X-SWARE-Spam-Status: No, hits=-6.3 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,RCVD_IN_DNSWL_HI,RCVD_IN_HOSTKARMA_W,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; Wed, 04 Apr 2012 19:14:35 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q34JEZ8A010938 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 4 Apr 2012 15:14:35 -0400 Received: from host2.jankratochvil.net (ovpn-116-28.ams2.redhat.com [10.36.116.28]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q34JEKGe007981 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO) for ; Wed, 4 Apr 2012 15:14:29 -0400 Date: Wed, 04 Apr 2012 19:14:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: [downstream patch FYI] workaround stale frame_info * (PR 13866) Message-ID: <20120404191416.GA29603@host2.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) 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: 2012-04/txt/msg00058.txt.bz2 Hi, I did not look at which commit caused this regression but apparently it was introduced at least with multi-inferiors. I understand this fix is not right fix of the crash; but in most GDB cases one does not use multi-inferior so why to regress single-inferior by it. Some more simple solutions still fix the single-inferior mode but they regressed the multi-inferior mode gdb.threads/no-unwaited-for-left.exp gdb.multi/base.exp so I had to put there that sorting magic. With proper C++ sanity check of stale live frame_info references the testcase would be simple without the "frame_garbage_collection" reproducer below. It is also reproducible just with valgrind but regularly running the whole testsuite under valgrind I did not find feasible. No regressions on {x86_64,x86_64-m32,i686}-fedora17-linux-gnu. Thanks, Jan gdb/ 2012-04-04 Jan Kratochvil Workaround PR backtrace/13866. * progspace.c (switch_to_program_space_and_thread): Try not to call switch_to_thread. --- a/gdb/progspace.c +++ b/gdb/progspace.c @@ -481,17 +481,28 @@ save_current_space_and_thread (void) void switch_to_program_space_and_thread (struct program_space *pspace) { - struct inferior *inf; + struct inferior *inf = current_inferior (); - inf = find_inferior_for_program_space (pspace); + if (inf->pspace != pspace) + inf = find_inferior_for_program_space (pspace); if (inf != NULL) { - struct thread_info *tp; + struct thread_info *tp, *current_tp = NULL; + + if (ptid_get_pid (inferior_ptid) == inf->pid) + current_tp = find_thread_ptid (inferior_ptid); tp = any_live_thread_of_process (inf->pid); if (tp != NULL) { - switch_to_thread (tp->ptid); + /* Prefer primarily thread not THREAD_EXITED and secondarily thread + not EXECUTING. */ + if (current_tp == NULL + || (tp->state != THREAD_EXITED + && current_tp->state == THREAD_EXITED) + || (!tp->executing && current_tp->executing)) + switch_to_thread (tp->ptid); + /* Switching thread switches pspace implicitly. We're done. */ return; Reproducer with: ./gdb -nx ~/t/thread -ex 'b 24' -ex r -ex 'until 25' Breakpoint 1, main () at /home/jkratoch/t/thread.c:24 24 v++; Segmentation fault (core dumped) #include #include #include static int v; static void *start (void *arg) { v++; v++; v++; v++; sleep (100); return arg; } int main (void) { pthread_t thread1; int i; i = pthread_create (&thread1, NULL, start, NULL); assert (i == 0); v++; v++; v++; v++; i = pthread_join (thread1, NULL); assert (i == 0); return 0; } --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1522,12 +1522,30 @@ frame_observer_target_changed (struct target_ops *target) reinit_frame_cache (); } +typedef struct obstack obstack_s; +DEF_VEC_O (obstack_s); +static VEC (obstack_s) *frame_poison_vec; + +void frame_garbage_collection (void); +void +frame_garbage_collection (void) +{ + struct obstack *obstack_p; + int ix; + + for (ix = 0; VEC_iterate (obstack_s, frame_poison_vec, ix, obstack_p); ix++) + obstack_free (obstack_p, 0); + + VEC_free (obstack_s, frame_poison_vec); + frame_poison_vec = NULL; +} + /* Flush the entire frame cache. */ void reinit_frame_cache (void) { - struct frame_info *fi; + struct frame_info *fi, *fi_prev; /* Tear down all frame caches. */ for (fi = current_frame; fi != NULL; fi = fi->prev) @@ -1538,8 +1556,14 @@ reinit_frame_cache (void) fi->base->unwind->dealloc_cache (fi, fi->base_cache); } + for (fi = current_frame; fi != NULL; fi = fi_prev) + { + fi_prev = fi->prev; + memset (fi, 0, sizeof (*fi)); + } + VEC_safe_push (obstack_s, frame_poison_vec, &frame_cache_obstack); + /* Since we can't really be sure what the first object allocated was. */ - obstack_free (&frame_cache_obstack, 0); obstack_init (&frame_cache_obstack); if (current_frame != NULL) --- a/gdb/top.c +++ b/gdb/top.c @@ -359,6 +359,11 @@ prepare_execute_command (void) if (non_stop) target_dcache_invalidate (); + { + extern void frame_garbage_collection (void); + frame_garbage_collection (); + } + return cleanup; }