From patchwork Thu Jul 3 15:13:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 1885 Received: (qmail 13337 invoked by alias); 3 Jul 2014 15:14:00 -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 13232 invoked by uid 89); 3 Jul 2014 15:13:59 -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_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, 03 Jul 2014 15:13:43 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s63FDgWL009459 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Thu, 3 Jul 2014 11:13:42 -0400 Received: from brno.lan (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s63FDQOo021950 for ; Thu, 3 Jul 2014 11:13:41 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 7/9] Canceling pagination caused by execution command from command line aborts readline/gdb Date: Thu, 3 Jul 2014 16:13:21 +0100 Message-Id: <1404400406-16708-14-git-send-email-palves@redhat.com> In-Reply-To: <1404400406-16708-1-git-send-email-palves@redhat.com> References: <1404400406-16708-1-git-send-email-palves@redhat.com> This fixes: $ ./gdb program -ex "set height 2" -ex "start" ... Reading symbols from /home/pedro/gdb/tests/threads...done. ---Type to continue, or q to quit---^CQuit << ctrl-c triggers a Quit *type something* readline: readline_callback_read_char() called with no handler! Aborted $ Usually, if an error propagates all the way to the top level, we'll re-enable stdin, in case the command that was running was a synchronous command. That's done in the event loop's actual loop (event-loop.c:start_event_loop). However, if a foreground execution command is run before the event loop starts and throws, nothing is presently reenabling stdin, which leaves sync_execution set. When we do start the event loop, because sync_execution is still (mistakenly) set, display_gdb_prompt removes the readline input callback, even though stdin is registered in the event loop. Any input from here on results in readline aborting. Such commands are run through catch_command_errors, catch_command_errors_const, so add the tweak there. gdb/ 2014-07-03 Pedro Alves PR gdb/17072 * main.c: Include event-top.h. (handle_command_errors): New function. (catch_command_errors, catch_command_errors_const): Use it. gdb/testsuite/ 2014-07-03 Pedro Alves * gdb.base/paginate-execution-startup.c: New file. * gdb.base/paginate-execution-startup.exp: New file. * lib/gdb.exp (pagination_prompt): New global. (default_gdb_spawn): New procedure, factored out from default_gdb_spawn. (default_gdb_start): Adjust to call default_gdb_spawn. (gdb_spawn): New procedure. --- gdb/main.c | 30 +++- .../gdb.base/paginate-execution-startup.c | 30 ++++ .../gdb.base/paginate-execution-startup.exp | 175 +++++++++++++++++++++ gdb/testsuite/lib/gdb.exp | 61 +++++-- 4 files changed, 276 insertions(+), 20 deletions(-) create mode 100644 gdb/testsuite/gdb.base/paginate-execution-startup.c create mode 100644 gdb/testsuite/gdb.base/paginate-execution-startup.exp diff --git a/gdb/main.c b/gdb/main.c index 1d77bd3..b51ff89 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -46,6 +46,7 @@ #include "filenames.h" #include "filestuff.h" #include +#include "event-top.h" /* The selected interpreter. This will be used as a set command variable, so it should always be malloc'ed - since @@ -337,6 +338,25 @@ captured_command_loop (void *data) return 1; } +/* Handle command errors thrown from within + catch_command_errors/catch_command_errors_const. */ + +static int +handle_command_errors (volatile struct gdb_exception e) +{ + if (e.reason < 0) + { + exception_print (gdb_stderr, e); + + /* If any exception escaped to here, we better enable stdin. + Otherwise, any command that calls async_disable_stdin, and + then throws, will leave stdin inoperable. */ + async_enable_stdin (); + return 0; + } + return 1; +} + /* Type of the command callback passed to catch_command_errors. */ typedef void (catch_command_errors_ftype) (char *, int); @@ -353,10 +373,7 @@ catch_command_errors (catch_command_errors_ftype *command, { command (arg, from_tty); } - exception_print (gdb_stderr, e); - if (e.reason < 0) - return 0; - return 1; + return handle_command_errors (e); } /* Type of the command callback passed to catch_command_errors_const. */ @@ -375,10 +392,7 @@ catch_command_errors_const (catch_command_errors_const_ftype *command, { command (arg, from_tty); } - exception_print (gdb_stderr, e); - if (e.reason < 0) - return 0; - return 1; + return handle_command_errors (e); } /* Arguments of --command option and its counterpart. */ diff --git a/gdb/testsuite/gdb.base/paginate-execution-startup.c b/gdb/testsuite/gdb.base/paginate-execution-startup.c new file mode 100644 index 0000000..7457b18 --- /dev/null +++ b/gdb/testsuite/gdb.base/paginate-execution-startup.c @@ -0,0 +1,30 @@ +/* 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 . */ + +static void +after_sleep (void) +{ + return; /* after sleep */ +} + +int +main (void) +{ + sleep (3); + after_sleep (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/paginate-execution-startup.exp b/gdb/testsuite/gdb.base/paginate-execution-startup.exp new file mode 100644 index 0000000..77822fb --- /dev/null +++ b/gdb/testsuite/gdb.base/paginate-execution-startup.exp @@ -0,0 +1,175 @@ +# 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 . + +# A collection of tests related to pagination resulting from running +# execution commands directly from the command line, with "-ex". + +standard_testfile + +if {[build_executable "failed to prepare" $testfile $srcfile debug] == -1} { + return -1 +} + +global GDBFLAGS +set saved_gdbflags $GDBFLAGS + +# Returns true if the board can 'gdb -ex "start"', false otherwise. + +proc probe_can_run_cmdline {} { + global srcfile binfile + global saved_gdbflags GDBFLAGS + global gdb_prompt + + set GDBFLAGS $saved_gdbflags + append GDBFLAGS " -ex \"set height 0\"" + append GDBFLAGS " -ex \"start\"" + append GDBFLAGS " --args \"$binfile\"" + + with_test_prefix "probe support" { + set test "run to main" + + gdb_exit + set res [gdb_spawn] + if { $res != 0} { + fail $test + return -1 + } + + set res -1 + gdb_test_multiple "" $test { + -re "main .* at .*$srcfile.*$gdb_prompt $" { + set res 1 + pass $test + } + -re "Don't know how to run.*$gdb_prompt $" { + set res 0 + unsupported $test + } + } + return $res + } +} + +# Check that we handle pagination correctly when it triggers due to an +# execution command entered directly on the command line. + +proc test_fg_execution_pagination_return {} { + global binfile + global saved_gdbflags GDBFLAGS + global gdb_prompt pagination_prompt + + set GDBFLAGS $saved_gdbflags + append GDBFLAGS " -ex \"set height 2\"" + append GDBFLAGS " -ex \"start\"" + append GDBFLAGS " --args \"$binfile\"" + + with_test_prefix "return" { + set test "run to pagination" + + gdb_exit + set res [gdb_spawn] + if { $res != 0} { + fail $test + return $res + } + gdb_test_multiple "" $test { + -re "$pagination_prompt$" { + pass $test + } + -re "$gdb_prompt $" { + fail $test + } + } + + send_gdb "\n" + + set saw_pagination_prompt 0 + set test "send \\n to GDB" + gdb_test_multiple "" $test { + -re "$pagination_prompt$" { + set saw_pagination_prompt 1 + send_gdb "\n" + exp_continue + } + -notransfer -re "" { + # Otherwise gdb_test_multiple considers this an error. + exp_continue + } + -re "$gdb_prompt $" { + gdb_assert $saw_pagination_prompt $test + } + } + + gdb_test "p 1" " = 1" "GDB accepts further input" + } +} + +# Check that we handle canceling pagination correctly when it triggers +# due to an execution command entered directly on the command line. + +proc test_fg_execution_pagination_cancel { how } { + global binfile + global saved_gdbflags GDBFLAGS + global gdb_prompt pagination_prompt + + set GDBFLAGS $saved_gdbflags + + append GDBFLAGS " -ex \"set height 2\"" + append GDBFLAGS " -ex \"start\"" + append GDBFLAGS " --args \"$binfile\"" + + with_test_prefix "ctrl-c" { + set test "run to pagination" + + gdb_exit + set res [gdb_spawn] + if { $res != 0} { + fail $test + return $res + } + gdb_test_multiple "" $test { + -re "$pagination_prompt$" { + pass $test + } + -notransfer -re "" { + # Otherwise gdb_test_multiple considers this an error. + exp_continue + } + } + + set test "cancel pagination" + if { $how == "ctrl-c" } { + send_gdb "\003" + } else { + send_gdb "q\n" + + } + gdb_test_multiple "" $test { + -re "Quit\r\n$gdb_prompt $" { + pass $test + } + } + + gdb_test "p 1" " = 1" "GDB accepts further input" + } +} + +if {[probe_can_run_cmdline] > 0} { + test_fg_execution_pagination_return + test_fg_execution_pagination_cancel "ctrl-c" + test_fg_execution_pagination_cancel "quit" +} + +set GDBFLAGS $saved_gdbflags diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 36cbf05..3533ee3 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -69,6 +69,9 @@ if ![info exists gdb_prompt] then { set gdb_prompt "\[(\]gdb\[)\]" } +# A regexp that matches the pagination prompt. +set pagination_prompt "---Type to continue, or q to quit---" + # The variable fullname_syntax_POSIX is a regexp which matches a POSIX # absolute path ie. /foo/ set fullname_syntax_POSIX {/[^\n]*/} @@ -1425,19 +1428,12 @@ proc gdb_file_cmd { arg } { } } -# -# start gdb -- start gdb running, default procedure -# -# When running over NFS, particularly if running many simultaneous -# tests on different hosts all using the same server, things can -# get really slow. Give gdb at least 3 minutes to start up. -# -proc default_gdb_start { } { - global verbose use_gdb_stub +# Default gdb_spawn procedure. + +proc default_gdb_spawn { } { + global use_gdb_stub global GDB global INTERNAL_GDBFLAGS GDBFLAGS - global gdb_prompt - global timeout global gdb_spawn_id gdb_stop_suppressing_tests @@ -1468,21 +1464,45 @@ proc default_gdb_start { } { perror "Spawning $GDB failed." return 1 } + set gdb_spawn_id -1 + return 0 +} + +# Default gdb_start procedure. + +proc default_gdb_start { } { + global gdb_prompt + global gdb_spawn_id + + if [info exists gdb_spawn_id] { + return 0 + } + + set res [gdb_spawn] + if { $res != 0} { + return $res + } + + # When running over NFS, particularly if running many simultaneous + # tests on different hosts all using the same server, things can + # get really slow. Give gdb at least 3 minutes to start up. gdb_expect 360 { -re "\[\r\n\]$gdb_prompt $" { verbose "GDB initialized." } -re "$gdb_prompt $" { perror "GDB never initialized." + unset gdb_spawn_id return -1 } timeout { perror "(timeout) GDB never initialized after 10 seconds." remote_close host + unset gdb_spawn_id return -1 } } - set gdb_spawn_id -1 + # force the height to "unlimited", so no pagers get used send_gdb "set height 0\n" @@ -3285,6 +3305,23 @@ proc gdb_clear_suppressed { } { set suppress_flag 0 } +# Spawn the gdb process. +# +# This doesn't expect any output or do any other initialization, +# leaving those to the caller. +# +# Overridable function -- you can override this function in your +# baseboard file. + +proc gdb_spawn { } { + default_gdb_spawn +} + +# Start gdb running, wait for prompt, and disable the pagers. + +# Overridable function -- you can override this function in your +# baseboard file. + proc gdb_start { } { default_gdb_start }