Make sure terminal settings are restored before exiting
authorPatrick Palka <patrick@parcs.ath.cx>
Mon, 27 Jul 2015 15:54:07 +0000 (11:54 -0400)
committerPatrick Palka <patrick@parcs.ath.cx>
Wed, 29 Jul 2015 12:39:41 +0000 (08:39 -0400)
When exiting GDB -- whether it's via the "quit" command, via a SIGTERM,
or otherwise -- we should leave the terminal in the state we acquired
it.  To that end, we have to undo any modifications that may have been
made by the TUI (ncurses) or by the CLI (readline).

Tested on x86_64 Debian Stretch.

gdb/ChangeLog:

* top.c: Include "tui/tui.h".
(undo_terminal_modifications_before_exit): New static function.
(quit_force): Use it.

gdb/testsuite/ChangeLog:

* gdb.base/batch-preserve-term-settings.exp
(test_terminal_settings_preserved_after_cli_exit): New test.

gdb/ChangeLog
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/batch-preserve-term-settings.exp
gdb/top.c

index 2e621847964f9858a6c7d534626a388b6a4818f7..0c24f0c4e32cf9a2172690fbb03881e8991543f2 100644 (file)
@@ -1,3 +1,9 @@
+2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
+
+       * top.c: Include "tui/tui.h".
+       (undo_terminal_modifications_before_exit): New static function.
+       (quit_force): Use it.
+
 2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
 
        * target.c (terminal_state): Initialize to terminal_is_ours.
index 6fd5a36c68b2e72826a2f9d73fc2d01af4d1b1a1..ee0af2adc70a94d7c919a2d92dacca7afc338e08 100644 (file)
@@ -1,3 +1,8 @@
+2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
+
+       * gdb.base/batch-preserve-term-settings.exp
+       (test_terminal_settings_preserved_after_cli_exit): New test.
+
 2015-07-29  Patrick Palka  <patrick@parcs.ath.cx>
 
        * gdb.base/batch-preserve-term-settings.exp: Remove top-level
index 97ffaa4acf36785af60f00794cb12daa88e2d983..ca6f1735558998017ef768b5a690cc0fd4b959e0 100644 (file)
@@ -176,4 +176,96 @@ proc test_terminal_settings_preserved {} {
     exit_shell
 }
 
-test_terminal_settings_preserved
+# Check that quitting from the CLI via the "quit" command does not leave the
+# terminal in the wrong state.  The GDB commands CMDS are executed before
+# quitting.
+
+proc test_terminal_settings_preserved_after_cli_exit { cmds } {
+    global file_arg
+    global GDB INTERNAL_GDBFLAGS GDBFLAGS
+    global gdb_prompt
+    global shell_prompt_re
+
+    if ![spawn_shell] {
+       return
+    }
+
+    set saved_gdbflags $GDBFLAGS
+
+    set stty_supported [run_stty "stty before" stty_before]
+
+    set test "start gdb"
+    send_gdb "$GDB $INTERNAL_GDBFLAGS $GDBFLAGS [host_info gdb_opts] --args \"$file_arg\"\n"
+    gdb_expect {
+       -re "$gdb_prompt $" {
+           pass $test
+       }
+       timeout {
+           fail "$test (timeout)"
+       }
+       eof {
+           fail "$test (eof)"
+       }
+    }
+
+    foreach cmd $cmds {
+       set test "run command $cmd"
+       send_gdb "$cmd\n"
+       gdb_expect {
+           -re "$gdb_prompt $" {
+               pass $test
+           }
+           timeout {
+               fail "$test (timeout)"
+           }
+           eof {
+               fail "$test (eof)"
+           }
+       }
+    }
+
+    set test "quit gdb"
+    send_gdb "quit\n"
+    gdb_expect {
+       -re "(y or n)" {
+           send_gdb "y\n"
+           exp_continue
+       }
+       -re ".*$shell_prompt_re$" {
+           pass $test
+       }
+       timeout {
+           fail "$test (timeout)"
+       }
+       eof {
+           fail "$test (eof)"
+       }
+    }
+
+    set test "terminal settings preserved"
+    if $stty_supported {
+       run_stty "stty after" stty_after
+
+       gdb_assert [string equal $stty_before $stty_after] $test
+    } else {
+       unsupported "$test (no stty)"
+    }
+
+    exit_shell
+}
+
+with_test_prefix "batch run" {
+    test_terminal_settings_preserved
+}
+
+with_test_prefix "cli exit" {
+    test_terminal_settings_preserved_after_cli_exit { }
+}
+
+with_test_prefix "cli exit after start cmd" {
+    test_terminal_settings_preserved_after_cli_exit { "start" }
+}
+
+with_test_prefix "cli exit after run cmd" {
+    test_terminal_settings_preserved_after_cli_exit { "run" }
+}
index 1e30b1cb2b13a08c7326d1f088d4cbec44523024..3e88ac6490bd13442d9712011d84265427526e29 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
 #include "tracepoint.h"
 #include "inf-loop.h"
 
+#if defined(TUI)
+# include "tui/tui.h"
+#endif
+
 extern void initialize_all_files (void);
 
 #define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt
@@ -1486,6 +1490,21 @@ quit_confirm (void)
   return qr;
 }
 
+/* Prepare to exit GDB cleanly by undoing any changes made to the
+   terminal so that we leave the terminal in the state we acquired it.  */
+
+static void
+undo_terminal_modifications_before_exit (void)
+{
+  target_terminal_ours ();
+#if defined(TUI)
+  tui_disable ();
+#endif
+  if (async_command_editing_p)
+    gdb_disable_readline ();
+}
+
+
 /* Quit without asking for confirmation.  */
 
 void
@@ -1494,6 +1513,8 @@ quit_force (char *args, int from_tty)
   int exit_code = 0;
   struct qt_args qt;
 
+  undo_terminal_modifications_before_exit ();
+
   /* An optional expression may be used to cause gdb to terminate with the 
      value of that expression.  */
   if (args)