From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4138 invoked by alias); 15 Feb 2012 20:14:05 -0000 Received: (qmail 3903 invoked by uid 22791); 15 Feb 2012 20:14:02 -0000 X-SWARE-Spam-Status: No, hits=-7.0 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; Wed, 15 Feb 2012 20:13:28 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q1FKDRqL011237 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 15 Feb 2012 15:13:27 -0500 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id q1FKDQeT004241; Wed, 15 Feb 2012 15:13:27 -0500 Received: from barimba (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id q1FKDP3V012117; Wed, 15 Feb 2012 15:13:25 -0500 From: Tom Tromey To: Pedro Alves Cc: Jan Kratochvil , gdb-patches@sourceware.org Subject: Re: RFC: fix crash when inferior exits during "continue" References: <20120210144040.GA28038@host2.jankratochvil.net> <87ty2ya1ys.fsf@fleche.redhat.com> <20120214134417.GA6730@redhat.com> <4F3A6D51.5010904@redhat.com> Date: Wed, 15 Feb 2012 22:24:00 -0000 In-Reply-To: <4F3A6D51.5010904@redhat.com> (Pedro Alves's message of "Tue, 14 Feb 2012 14:18:57 +0000") Message-ID: <87d39fn9cq.fsf@fleche.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.93 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain 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/msg00312.txt.bz2 >>>>> "Pedro" == Pedro Alves writes: Pedro> Yeah. We also don't randomly switch to another thread if the previous Pedro> selected thread exits (and this is the reason we have "exited" threads). Pedro> Otherwise, if the user is typing Pedro> (gdb) some_command_that_applies_to_the_current_thread Pedro> and the current thread disappears while the user is typing, Pedro> the command ends up being applied to a random thread, which is Pedro> not good. This makes sense to me if the user entered a background command. But why not switch if the last command was a foreground command? Pedro> - Make make_cleanup_restore_current_thread "lock" the current Pedro> inferior, so it isn't removed even if it is "removable". Pedro> We do something similar for threads -- That's the whole reason Pedro> for thread_info->refcount. (This is also Jan's suggestion.) What do you think of the appended? Tom 2012-02-15 Tom Tromey PR c++/13653: * thread.c (struct current_thread_cleanup) : New field. (do_restore_current_thread_cleanup): Restore 'removable' field. (restore_current_thread_cleanup_dtor): Likewise. (make_cleanup_restore_current_thread): Initialize new field. 2012-02-15 Tom Tromey * gdb.base/inferior-died.c: New file. * gdb.base/inferior-died.exp: New file. diff --git a/gdb/testsuite/gdb.base/inferior-died.c b/gdb/testsuite/gdb.base/inferior-died.c new file mode 100644 index 0000000..66227cf --- /dev/null +++ b/gdb/testsuite/gdb.base/inferior-died.c @@ -0,0 +1,37 @@ +/* Test for fork-related gdb bug + + Copyright 2012 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 + +void function(void) +{ + exit (0); /* Break here */ +} + +int main() +{ + pid_t child = fork (); + + if (child == 0) + function (); + else + waitpid (child, NULL, 0); +} diff --git a/gdb/testsuite/gdb.base/inferior-died.exp b/gdb/testsuite/gdb.base/inferior-died.exp new file mode 100644 index 0000000..458dd61 --- /dev/null +++ b/gdb/testsuite/gdb.base/inferior-died.exp @@ -0,0 +1,56 @@ +# Copyright 2012 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 . + +if { [is_remote target] || ![isnative] } then { + unsupported "inferior-died.exp" + continue +} + +# Until "set follow-fork-mode" and "catch fork" are implemented on +# other targets... +# +if {![istarget "hppa*-hp-hpux*"] && ![istarget "*-*-linux*"]} then { + unsupported "inferior-died.exp" + continue +} + +if { ![support_displaced_stepping] } { + unsupported "inferior-died.exp" + return -1 +} + +set testfile "inferior-died" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} + +if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c] } { + return -1 +} + +gdb_test_no_output "set detach-on-fork off" +gdb_test_no_output "set target-async on" +gdb_test_no_output "set non-stop on" + +if ![runto_main] { + return +} + +set line [gdb_get_line_number "Break here"] +gdb_breakpoint $srcfile:$line + +gdb_continue_to_breakpoint "breakpoint" + +gdb_test "inferior 2" "Switching to inferior 2.*" +gdb_test "continue" "exited normally.*" diff --git a/gdb/thread.c b/gdb/thread.c index 9a29383..c7c9699 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1072,6 +1072,7 @@ struct current_thread_cleanup int selected_frame_level; int was_stopped; int inf_id; + int was_removable; }; static void @@ -1095,6 +1096,8 @@ do_restore_current_thread_cleanup (void *arg) set_current_inferior (find_inferior_id (old->inf_id)); } + current_inferior ()->removable = old->was_removable; + /* The running state of the originally selected thread may have changed, so we have to recheck it here. */ if (!ptid_equal (inferior_ptid, null_ptid) @@ -1112,10 +1115,14 @@ restore_current_thread_cleanup_dtor (void *arg) { struct current_thread_cleanup *old = arg; struct thread_info *tp; + struct inferior *inf; tp = find_thread_ptid (old->inferior_ptid); if (tp) tp->refcount--; + inf = find_inferior_id (old->inf_id); + if (inf != NULL) + inf->removable = old->was_removable; xfree (old); } @@ -1129,6 +1136,7 @@ make_cleanup_restore_current_thread (void) old = xmalloc (sizeof (struct current_thread_cleanup)); old->inferior_ptid = inferior_ptid; old->inf_id = current_inferior ()->num; + old->was_removable = current_inferior ()->removable; if (!ptid_equal (inferior_ptid, null_ptid)) { @@ -1156,6 +1164,8 @@ make_cleanup_restore_current_thread (void) tp->refcount++; } + current_inferior ()->removable = 0; + return make_cleanup_dtor (do_restore_current_thread_cleanup, old, restore_current_thread_cleanup_dtor); }