Fix terminal state corruption when starting a program from within TUI

The TUI terminal state becomes corrupted (e.g. key sequences such as
Alt_F and Alt_B no longer work) when one attaches to an inferior process
(via "run" or "attach") from within TUI.  This terminal corruption
remains until you switch out of TUI mode.

This happens because the terminal state is not properly saved when
switching to and out from TUI mode.  Although the functions tui_enable()
and tui_disable() both call the function target_terminal_save_ours() to
save the terminal state, this function is a no-op unless GDB has already
attached to an inferior process.  This is because only the "native"
target has a useful implementation of target_terminal_save_ours()
(namely child_terminal_save_ours()) and we only have the "native" target
in our target vector if GDB has already attached to an inferior process.

So without an inferior process, switching to and from TUI mode does not
actually save the terminal state.  Therefore when you attach to an
inferior process from within TUI mode, the proper terminal state is not
restored (after swapping from the inferior's terminal back to the GDB
terminal).

To fix this we just have to ensure that the terminal state is always
being properly saved when switching from and to TUI mode.  To achieve
this, this patch removes the polymorphic function
target_terminal_save_ours() and replaces it with a regular function
gdb_save_tty_state() that always saves the terminal state.

Tested on x86_64-unknown-linux-gnu by running "make check", no new
regressions.

gdb/ChangeLog:
	* target.h (struct target_ops::to_terminal_save_ours): Remove
	declaration.
	(target_terminal_save_ours): Remove macro.
	* target-delegates.c: Regenerate.
	* inf-child.c (inf_child_target): Don't set the nonexistent
	field to_terminal_save_ours.
	* inferior.h (child_terminal_save_ours): Remove declaration.
	* terminal.h (gdb_save_tty_state): New declaration.
	* inflow.c (child_terminal_save_ours): Rename to ...
	(gdb_save_tty_state): ... this.
	* tui/tui.c: Include terminal.h.
	(tui_enable): Use gdb_save_tty_state instead of
	target_terminal_save_ours.
	(tui_disable): Likewise.
This commit is contained in:
Patrick Palka 2014-08-25 10:40:32 -04:00 committed by Sergio Durigan Junior
parent ee92b0dd4e
commit 3278a9f568
7 changed files with 6 additions and 42 deletions

View File

@ -481,7 +481,6 @@ inf_child_target (void)
t->to_terminal_init = child_terminal_init;
t->to_terminal_inferior = child_terminal_inferior;
t->to_terminal_ours_for_output = child_terminal_ours_for_output;
t->to_terminal_save_ours = child_terminal_save_ours;
t->to_terminal_ours = child_terminal_ours;
t->to_terminal_info = child_terminal_info;
t->to_post_startup_inferior = inf_child_post_startup_inferior;

View File

@ -110,8 +110,6 @@ extern void child_terminal_info (struct target_ops *self, const char *, int);
extern void term_info (char *, int);
extern void child_terminal_save_ours (struct target_ops *self);
extern void child_terminal_ours (struct target_ops *self);
extern void child_terminal_ours_for_output (struct target_ops *self);

View File

@ -241,7 +241,7 @@ child_terminal_init_with_pgrp (int pgrp)
and gdb must be able to restore it correctly. */
void
child_terminal_save_ours (struct target_ops *self)
gdb_save_tty_state (void)
{
if (gdb_has_a_terminal ())
{

View File

@ -812,28 +812,6 @@ debug_terminal_ours (struct target_ops *self)
fputs_unfiltered (")\n", gdb_stdlog);
}
static void
delegate_terminal_save_ours (struct target_ops *self)
{
self = self->beneath;
self->to_terminal_save_ours (self);
}
static void
tdefault_terminal_save_ours (struct target_ops *self)
{
}
static void
debug_terminal_save_ours (struct target_ops *self)
{
fprintf_unfiltered (gdb_stdlog, "-> %s->to_terminal_save_ours (...)\n", debug_target.to_shortname);
debug_target.to_terminal_save_ours (&debug_target);
fprintf_unfiltered (gdb_stdlog, "<- %s->to_terminal_save_ours (", debug_target.to_shortname);
target_debug_print_struct_target_ops_p (&debug_target);
fputs_unfiltered (")\n", gdb_stdlog);
}
static void
delegate_terminal_info (struct target_ops *self, const char *arg1, int arg2)
{
@ -3814,8 +3792,6 @@ install_delegators (struct target_ops *ops)
ops->to_terminal_ours_for_output = delegate_terminal_ours_for_output;
if (ops->to_terminal_ours == NULL)
ops->to_terminal_ours = delegate_terminal_ours;
if (ops->to_terminal_save_ours == NULL)
ops->to_terminal_save_ours = delegate_terminal_save_ours;
if (ops->to_terminal_info == NULL)
ops->to_terminal_info = delegate_terminal_info;
if (ops->to_kill == NULL)
@ -4068,7 +4044,6 @@ install_dummy_methods (struct target_ops *ops)
ops->to_terminal_inferior = tdefault_terminal_inferior;
ops->to_terminal_ours_for_output = tdefault_terminal_ours_for_output;
ops->to_terminal_ours = tdefault_terminal_ours;
ops->to_terminal_save_ours = tdefault_terminal_save_ours;
ops->to_terminal_info = default_terminal_info;
ops->to_kill = tdefault_kill;
ops->to_load = tdefault_load;
@ -4212,7 +4187,6 @@ init_debug_target (struct target_ops *ops)
ops->to_terminal_inferior = debug_terminal_inferior;
ops->to_terminal_ours_for_output = debug_terminal_ours_for_output;
ops->to_terminal_ours = debug_terminal_ours;
ops->to_terminal_save_ours = debug_terminal_save_ours;
ops->to_terminal_info = debug_terminal_info;
ops->to_kill = debug_kill;
ops->to_load = debug_load;

View File

@ -506,8 +506,6 @@ struct target_ops
TARGET_DEFAULT_IGNORE ();
void (*to_terminal_ours) (struct target_ops *)
TARGET_DEFAULT_IGNORE ();
void (*to_terminal_save_ours) (struct target_ops *)
TARGET_DEFAULT_IGNORE ();
void (*to_terminal_info) (struct target_ops *, const char *, int)
TARGET_DEFAULT_FUNC (default_terminal_info);
void (*to_kill) (struct target_ops *)
@ -1417,14 +1415,6 @@ extern void target_terminal_inferior (void);
extern int target_supports_terminal_ours (void);
/* Save our terminal settings.
This is called from TUI after entering or leaving the curses
mode. Since curses modifies our terminal this call is here
to take this change into account. */
#define target_terminal_save_ours() \
(*current_target.to_terminal_save_ours) (&current_target)
/* Print useful information about our terminal status, if such a thing
exists. */

View File

@ -101,6 +101,8 @@ extern void initialize_stdin_serial (void);
extern int gdb_has_a_terminal (void);
extern void gdb_save_tty_state (void);
/* Set the process group of the caller to its own pid, or do nothing
if we lack job control. */
extern int gdb_setpgid (void);

View File

@ -37,6 +37,7 @@
#include "inferior.h"
#include "symtab.h"
#include "source.h"
#include "terminal.h"
#include <ctype.h>
#include <signal.h>
@ -425,7 +426,7 @@ tui_enable (void)
tui_refresh_all_win ();
/* Update gdb's knowledge of its terminal. */
target_terminal_save_ours ();
gdb_save_tty_state ();
tui_update_gdb_sizes ();
}
@ -455,7 +456,7 @@ tui_disable (void)
tui_setup_io (0);
/* Update gdb's knowledge of its terminal. */
target_terminal_save_ours ();
gdb_save_tty_state ();
tui_active = 0;
tui_update_gdb_sizes ();