Make sure terminal settings are restored before exiting

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.
This commit is contained in:
Patrick Palka 2015-07-27 11:54:07 -04:00
parent 7afa63c624
commit 18206ca3f9
4 changed files with 125 additions and 1 deletions

View 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> 2015-07-29 Patrick Palka <patrick@parcs.ath.cx>
* target.c (terminal_state): Initialize to terminal_is_ours. * target.c (terminal_state): Initialize to terminal_is_ours.

View 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> 2015-07-29 Patrick Palka <patrick@parcs.ath.cx>
* gdb.base/batch-preserve-term-settings.exp: Remove top-level * gdb.base/batch-preserve-term-settings.exp: Remove top-level

View File

@ -176,4 +176,96 @@ proc test_terminal_settings_preserved {} {
exit_shell exit_shell
} }
# 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 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" }
}

View File

@ -67,6 +67,10 @@
#include "tracepoint.h" #include "tracepoint.h"
#include "inf-loop.h" #include "inf-loop.h"
#if defined(TUI)
# include "tui/tui.h"
#endif
extern void initialize_all_files (void); extern void initialize_all_files (void);
#define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt #define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt
@ -1486,6 +1490,21 @@ quit_confirm (void)
return qr; 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. */ /* Quit without asking for confirmation. */
void void
@ -1494,6 +1513,8 @@ quit_force (char *args, int from_tty)
int exit_code = 0; int exit_code = 0;
struct qt_args qt; struct qt_args qt;
undo_terminal_modifications_before_exit ();
/* An optional expression may be used to cause gdb to terminate with the /* An optional expression may be used to cause gdb to terminate with the
value of that expression. */ value of that expression. */
if (args) if (args)