From patchwork Thu Oct 9 18:00:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 3175 Received: (qmail 21009 invoked by alias); 9 Oct 2014 18:00:39 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 20872 invoked by uid 89); 9 Oct 2014 18:00:39 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD 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; Thu, 09 Oct 2014 18:00:35 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s99I0YJQ008980 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 9 Oct 2014 14:00:34 -0400 Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s99I0TSe020799 for ; Thu, 9 Oct 2014 14:00:33 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 3/4] PR gdb/17300: Input after "c -a" crashes readline/GDB Date: Thu, 9 Oct 2014 19:00:28 +0100 Message-Id: <1412877629-12052-4-git-send-email-palves@redhat.com> In-Reply-To: <1412877629-12052-1-git-send-email-palves@redhat.com> References: <1412877629-12052-1-git-send-email-palves@redhat.com> If all threads in the target were already running when the user does "c -a", nothing puts the inferior's terminal settings in effect and removes stdin from the event loop, which we must when running a foreground command. The result is that user input afterwards crashes readline/gdb: (gdb) start Temporary breakpoint 1 at 0x4005d4: file continue-all-already-running.c, line 23. Starting program: continue-all-already-running Temporary breakpoint 1, main () at continue-all-already-running.c:23 23 sleep (10); (gdb) c -a& Continuing. (gdb) c -a Continuing. p 1 readline: readline_callback_read_char() called with no handler! Aborted (core dumped) $ Backtrace: Program received signal SIGABRT, Aborted. 0x0000003b36a35877 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); (top-gdb) p 1 $1 = 1 (top-gdb) bt #0 0x0000003b36a35877 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 #1 0x0000003b36a36f68 in __GI_abort () at abort.c:89 #2 0x0000000000784aa9 in rl_callback_read_char () at readline/callback.c:116 #3 0x0000000000619181 in rl_callback_read_char_wrapper (client_data=0x0) at gdb/event-top.c:167 #4 0x0000000000619557 in stdin_event_handler (error=0, client_data=0x0) at gdb/event-top.c:373 #5 0x000000000061814a in handle_file_event (data=...) at gdb/event-loop.c:763 #6 0x0000000000617631 in process_event () at gdb/event-loop.c:340 #7 0x00000000006176f8 in gdb_do_one_event () at gdb/event-loop.c:404 #8 0x0000000000617748 in start_event_loop () at gdb/event-loop.c:429 #9 0x00000000006191b3 in cli_command_loop (data=0x0) at gdb/event-top.c:182 #10 0x000000000060f538 in current_interp_command_loop () at gdb/interps.c:318 #11 0x0000000000610701 in captured_command_loop (data=0x0) at gdb/main.c:323 #12 0x000000000060c3f5 in catch_errors (func=0x6106e6 , func_args=0x0, errstring=0x9002c1 "", mask=RETURN_MASK_ALL) at gdb/exceptions.c:237 #13 0x0000000000611bff in captured_main (data=0x7fffffffd780) at gdb/main.c:1151 #14 0x000000000060c3f5 in catch_errors (func=0x610afe , func_args=0x7fffffffd780, errstring=0x9002c1 "", mask=RETURN_MASK_ALL) at gdb/exceptions.c:237 #15 0x0000000000611c28 in gdb_main (args=0x7fffffffd780) at gdb/main.c:1159 #16 0x000000000045ef97 in main (argc=5, argv=0x7fffffffd888) at gdb/gdb.c:32 (top-gdb) Tested on x86_64 Fedora 20, native and gdbserver. gdb/ 2014-10-09 Pedro Alves PR gdb/17300 * infcmd.c (continue_1): If continuing all threads in the foreground, make sure the inferior's terminal settings are put in effect. gdb/testsuite/ 2014-10-09 Pedro Alves PR gdb/17300 * gdb.base/continue-all-already-running.c: New file. * gdb.base/continue-all-already-running.exp: New file. --- gdb/infcmd.c | 18 +++++ .../gdb.base/continue-all-already-running.c | 25 +++++++ .../gdb.base/continue-all-already-running.exp | 79 ++++++++++++++++++++++ 3 files changed, 122 insertions(+) create mode 100644 gdb/testsuite/gdb.base/continue-all-already-running.c create mode 100644 gdb/testsuite/gdb.base/continue-all-already-running.exp diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 0374533..d270664 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -735,6 +735,24 @@ continue_1 (int all_threads) iterate_over_threads (proceed_thread_callback, NULL); + if (sync_execution) + { + /* If all threads in the target were already running, + proceed_thread_callback ends up never calling proceed, + and so nothing calls this to put the inferior's terminal + settings in effect and remove stdin from the event loop, + which we must when running a foreground command. E.g.: + + (gdb) c -a& + Continuing. + + (gdb) c -a + Continuing. + + */ + target_terminal_inferior (); + } + /* Restore selected ptid. */ do_cleanups (old_chain); } diff --git a/gdb/testsuite/gdb.base/continue-all-already-running.c b/gdb/testsuite/gdb.base/continue-all-already-running.c new file mode 100644 index 0000000..a6516d5 --- /dev/null +++ b/gdb/testsuite/gdb.base/continue-all-already-running.c @@ -0,0 +1,25 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 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 + +int +main (void) +{ + sleep (10); + return 0; /* set break here */ +} diff --git a/gdb/testsuite/gdb.base/continue-all-already-running.exp b/gdb/testsuite/gdb.base/continue-all-already-running.exp new file mode 100644 index 0000000..6dde730 --- /dev/null +++ b/gdb/testsuite/gdb.base/continue-all-already-running.exp @@ -0,0 +1,79 @@ +# Copyright (C) 2014 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 . + +# Test that "c -a" doesn't leave GDB processing input, even if all +# threads were already running. PR gdb/17300. + +standard_testfile + +if { [prepare_for_testing ${testfile}.exp ${testfile} $srcfile] } { + return -1 +} + +gdb_test_no_output "set non-stop on" + +if ![runto_main] { + return +} + +set linenum [gdb_get_line_number "set break here"] +gdb_breakpoint "$linenum" + +gdb_test "c -a&" "Continuing\\." + +set test "no stop" +gdb_test_multiple "" $test { + -timeout 1 + timeout { + pass $test + } +} + +# Paranoia. Check that input works after bg command. +gdb_test "print 1" " = 1" + +# Continue in the foreground, and wait one second to make sure the +# inferior really starts running. If we get a prompt to soon (e.g., +# the program stops), this issues a fail. +set saw_continuing 0 +set test "c -a" +gdb_test_multiple "c -a" $test { + -timeout 1 + -re "Continuing\\." { + set saw_continuing 1 + exp_continue + } + timeout { + gdb_assert $saw_continuing $test + } +} + +# Type something while the inferior is running in the foreground. +send_gdb "print 2\n" + +# Poor buggy GDB would crash before the breakpoint was hit. +set test "breakpoint hit" +gdb_test_multiple "" $test { + -re "set break here ..\r\n$gdb_prompt " { + pass $test + } +} + +set test "print command result" +gdb_test_multiple "" $test { + -re " = 2\r\n$gdb_prompt $" { + pass $test + } +}