From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2205) id B6BCA38582BB; Tue, 8 Nov 2022 17:47:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B6BCA38582BB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1667929652; bh=ONA65lB2mhU3qkkBSOs8+Bk9mhDeHZwnZhWy4cWQX2Q=; h=From:To:Subject:Date:From; b=izI35p+O1BVhc6a+59/fOlQ0FMd1Iicu01vrD2Qp6m2RE+IFybia3r83ok7Q26f4Z zbor+xAG1VqEBqIMiHpNbgc4H2ZrMgdLU0KMbM4RAE1A95LoadR0xKfXIlFCB77FnT wIVvYUF1sNG9BU1Ge3SUSTZZtBUTye/nMOZV25fk= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom de Vries To: gdb-cvs@sourceware.org Subject: [binutils-gdb] [gdb/cli] Make quit really quit after remote connection closed X-Act-Checkin: binutils-gdb X-Git-Author: Tom de Vries X-Git-Refname: refs/heads/master X-Git-Oldrev: 2939f92abde7b98ed58710ab2719c9750ea4acad X-Git-Newrev: be6a2dca1505a4597fa3de71a85e7957d8d470ff Message-Id: <20221108174732.B6BCA38582BB@sourceware.org> Date: Tue, 8 Nov 2022 17:47:32 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dbe6a2dca1505= a4597fa3de71a85e7957d8d470ff commit be6a2dca1505a4597fa3de71a85e7957d8d470ff Author: Tom de Vries Date: Tue Nov 8 18:47:24 2022 +0100 [gdb/cli] Make quit really quit after remote connection closed =20 Consider a hello world a.out, started using gdbserver: ... $ gdbserver --once 127.0.0.1:2345 ./a.out Process ./a.out created; pid =3D 15743 Listening on port 2345 ... that we can connect to using gdb: ... $ gdb -ex "target remote 127.0.0.1:2345" Remote debugging using 127.0.0.1:2345 Reading /home/vries/a.out from remote target... ... 0x00007ffff7dd4550 in _start () from target:/lib64/ld-linux-x86-64.so.2 (gdb) ... =20 After that, we can for instance quit with confirmation: ... (gdb) quit A debugging session is active. =20 Inferior 1 [process 16691] will be killed. =20 Quit anyway? (y or n) y $ ... =20 Or, kill with confirmation and quit: ... (gdb) kill Kill the program being debugged? (y or n) y [Inferior 1 (process 16829) killed] (gdb) quit $ ... =20 Or, monitor exit, kill with confirmation, and quit: ... (gdb) monitor exit (gdb) kill Kill the program being debugged? (y or n) y Remote connection closed (gdb) quit $ ... =20 But when doing monitor exit followed by quit with confirmation, we get = the gdb prompt back, requiring us to do quit once more: ... (gdb) monitor exit (gdb) quit A debugging session is active. =20 Inferior 1 [process 16944] will be killed. =20 Quit anyway? (y or n) y Remote connection closed (gdb) quit $ ... =20 So, the first quit didn't quit. This happens as follows: - quit_command calls query_if_trace_running - a TARGET_CLOSE_ERROR is thrown - it's caught in remote_target::get_trace_status, but then rethrown because it's TARGET_CLOSE_ERROR - catch_command_errors catches the error, at which point the quit comma= nd has been aborted. =20 The TARGET_CLOSE_ERROR is defined as: ... /* Target throwing an error has been closed. Current command should = be aborted as the inferior state is no longer valid. */ TARGET_CLOSE_ERROR, ... so in a way this is expected behaviour. But aborting quit because the = inferior state (which we've already confirmed we're not interested in) is no lon= ger valid, and having to type quit again seems pointless. =20 Furthermore, the purpose of not catching errors thrown by query_if_trace_running as per commit 2f9d54cfcef ("make -gdb-exit call disconnect_tracing too, and don't lose history if the target errors on "quit""), was to make sure that error (_("Not confirmed.") had effect. =20 Fix this in quit_command by catching only the TARGET_CLOSE_ERROR except= ion during query_if_trace_running and reporting it: ... (gdb) monitor exit (gdb) quit A debugging session is active. =20 Inferior 1 [process 19219] will be killed. =20 Quit anyway? (y or n) y Remote connection closed $ ... =20 Tested on x86_64-linux. =20 PR server/15746 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D15746 Approved-By: Tom Tromey Diff: --- gdb/cli/cli-cmds.c | 15 ++++- gdb/testsuite/gdb.server/monitor-exit-quit.exp | 81 ++++++++++++++++++++++= ++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index fe4041662ef..bcfd3641ef5 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -488,7 +488,20 @@ quit_command (const char *args, int from_tty) if (!quit_confirm ()) error (_("Not confirmed.")); =20 - query_if_trace_running (from_tty); + try + { + query_if_trace_running (from_tty); + } + catch (const gdb_exception_error &ex) + { + if (ex.error =3D=3D TARGET_CLOSE_ERROR) + /* We don't care about this since we're quitting anyway, so keep + quitting. */ + exception_print (gdb_stderr, ex); + else + /* Rethrow, to properly handle error (_("Not confirmed.")). */ + throw; + } =20 quit_force (args ? &exit_code : NULL, from_tty); } diff --git a/gdb/testsuite/gdb.server/monitor-exit-quit.exp b/gdb/testsuite= /gdb.server/monitor-exit-quit.exp new file mode 100644 index 00000000000..fdf24520989 --- /dev/null +++ b/gdb/testsuite/gdb.server/monitor-exit-quit.exp @@ -0,0 +1,81 @@ +# This testcase is part of GDB, the GNU debugger. + +# Copyright 2022 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 quitting after monitor exit. + +load_lib gdbserver-support.exp + +standard_testfile server.c + +if { [skip_gdbserver_tests] } { + return 0 +} + +if {[build_executable $testfile.exp $testfile $srcfile debug] =3D=3D -1} { + return -1 +} + +save_vars { GDBFLAGS } { + # If GDB and GDBserver are both running locally, set the sysroot to av= oid + # reading files via the remote protocol. + if { ![is_remote host] && ![is_remote target] } { + set GDBFLAGS "$GDBFLAGS -ex \"set sysroot\"" + } + + clean_restart $binfile +} + +# Make sure we're disconnected, in case we're testing with an +# extended-remote board, therefore already connected. +gdb_test "disconnect" ".*" + +set target_exec [gdbserver_download_current_prog] + +set res [gdbserver_start "" $target_exec] + +set gdbserver_protocol [lindex $res 0] +set gdbserver_gdbport [lindex $res 1] +gdb_target_cmd $gdbserver_protocol $gdbserver_gdbport + +gdb_test_no_output "monitor exit" +gdb_test_no_output "set confirm off" + +set do_cleanup 1 + +gdb_test_multiple "quit" "" { + -re -wrap "" { + fail "$gdb_test_name (prompt)" + # Let default_gdb_exit do the cleanup. + set do_cleanup 0 + } + -early -re "DOSEXIT code" { + pass "$gdb_test_name" + } + -early eof { + pass "$gdb_test_name" + } +} + +# Cleanup, as in default_gdb_exit. +if { $do_cleanup } { + if ![is_remote host] { + remote_close host + } + unset gdb_spawn_id + unset ::gdb_tty_name + unset inferior_spawn_id +}