binutils-gdb/gdb/terminal.h
Simon Marchi 35ed81d4f4 Avoid GDB SIGTTOU on catch exec + set follow-exec-mode new (PR 23368)
Here's a summary of PR 23368:

  #include <unistd.h>
  int main (void)
  {
    char *exec_args[] = { "/bin/ls", NULL };
    execve (exec_args[0], exec_args, NULL);
  }

$ gdb -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run
...
[1]  + 13146 suspended (tty output)  gdb -q -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run
$

Here's what happens: when the inferior execs with "follow-exec-mode
new", we first "mourn" it before creating the new one.  This ends up
calling inflow_inferior_exit, which sets the per-inferior terminal state
to "is_ours":

  inf->terminal_state = target_terminal_state::is_ours;

At this point, the inferior's terminal_state is is_ours, while the
"reality", tracked by gdb_tty_state, is is_inferior (GDB doesn't own the
terminal).

Later, we continue processing the exec inferior event and decide we want
to stop (because of the "catch exec") and call target_terminal::ours to
make sure we own the terminal.  However, we don't actually go to the
target backend to change the settings, because the core thinks that no
inferior owns the terminal (inf->terminal_state is
target_terminal_state::is_ours, as checked in
target_terminal_is_ours_kind, for both inferiors).  When something in
readline tries to mess with the terminal settings, it generates a
SIGTTOU.

This patch fixes this by tranferring the state of the terminal from the
old inferior to the new inferior.

gdb/ChangeLog:

	PR gdb/23368
	* infrun.c (follow_exec): In the follow_exec_mode_new case,
	transfer terminal state from old new new inferior.
	* terminal.h (swap_terminal_info): New function.
	* inflow.c (swap_terminal_info): New function.
2018-10-23 17:00:41 -04:00

47 lines
1.5 KiB
C

/* Terminal interface definitions for GDB, the GNU Debugger.
Copyright (C) 1986-2018 Free Software Foundation, Inc.
This file is part of GDB.
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 <http://www.gnu.org/licenses/>. */
#if !defined (TERMINAL_H)
#define TERMINAL_H 1
struct inferior;
extern void new_tty_prefork (const char *);
extern void new_tty (void);
extern void new_tty_postfork (void);
extern void copy_terminal_info (struct inferior *to, struct inferior *from);
/* Exchange the terminal info and state between inferiors A and B. */
extern void swap_terminal_info (inferior *a, inferior *b);
extern pid_t create_tty_session (void);
/* Set up a serial structure describing standard input. In inflow.c. */
extern void initialize_stdin_serial (void);
extern void gdb_save_tty_state (void);
/* Take a snapshot of our initial tty state before readline/ncurses
have had a chance to alter it. */
extern void set_initial_gdb_ttystate (void);
#endif /* !defined (TERMINAL_H) */