Blame SOURCES/gdb-rhbz2015131-avoid-sigttou-forks-2of2.patch

985021
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
985021
From: Simon Marchi <simon.marchi@polymtl.ca>
985021
Date: Tue, 23 Oct 2018 17:00:33 -0400
985021
Subject: gdb-rhbz2015131-avoid-sigttou-forks-2of2.patch
985021
985021
;; Avoid GDB SIGTTOU on catch exec + set follow-exec-mode new (PR 23368)
985021
;; (Simon Marchi, related to RHBZ 2015131)
985021
985021
Here's a summary of PR 23368:
985021
985021
  #include <unistd.h>
985021
  int main (void)
985021
  {
985021
    char *exec_args[] = { "/bin/ls", NULL };
985021
    execve (exec_args[0], exec_args, NULL);
985021
  }
985021
985021
$ gdb -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run
985021
...
985021
[1]  + 13146 suspended (tty output)  gdb -q -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run
985021
$
985021
985021
Here's what happens: when the inferior execs with "follow-exec-mode
985021
new", we first "mourn" it before creating the new one.  This ends up
985021
calling inflow_inferior_exit, which sets the per-inferior terminal state
985021
to "is_ours":
985021
985021
  inf->terminal_state = target_terminal_state::is_ours;
985021
985021
At this point, the inferior's terminal_state is is_ours, while the
985021
"reality", tracked by gdb_tty_state, is is_inferior (GDB doesn't own the
985021
terminal).
985021
985021
Later, we continue processing the exec inferior event and decide we want
985021
to stop (because of the "catch exec") and call target_terminal::ours to
985021
make sure we own the terminal.  However, we don't actually go to the
985021
target backend to change the settings, because the core thinks that no
985021
inferior owns the terminal (inf->terminal_state is
985021
target_terminal_state::is_ours, as checked in
985021
target_terminal_is_ours_kind, for both inferiors).  When something in
985021
readline tries to mess with the terminal settings, it generates a
985021
SIGTTOU.
985021
985021
This patch fixes this by tranferring the state of the terminal from the
985021
old inferior to the new inferior.
985021
985021
gdb/ChangeLog:
985021
985021
	PR gdb/23368
985021
	* infrun.c (follow_exec): In the follow_exec_mode_new case,
985021
	transfer terminal state from old new new inferior.
985021
	* terminal.h (swap_terminal_info): New function.
985021
	* inflow.c (swap_terminal_info): New function.
985021
985021
diff --git a/gdb/inflow.c b/gdb/inflow.c
985021
--- a/gdb/inflow.c
985021
+++ b/gdb/inflow.c
985021
@@ -671,6 +671,22 @@ copy_terminal_info (struct inferior *to, struct inferior *from)
985021
   to->terminal_state = from->terminal_state;
985021
 }
985021
 
985021
+/* See terminal.h.  */
985021
+
985021
+void
985021
+swap_terminal_info (inferior *a, inferior *b)
985021
+{
985021
+  terminal_info *info_a
985021
+    = (terminal_info *) inferior_data (a, inflow_inferior_data);
985021
+  terminal_info *info_b
985021
+    = (terminal_info *) inferior_data (a, inflow_inferior_data);
985021
+
985021
+  set_inferior_data (a, inflow_inferior_data, info_b);
985021
+  set_inferior_data (b, inflow_inferior_data, info_a);
985021
+
985021
+  std::swap (a->terminal_state, b->terminal_state);
985021
+}
985021
+
985021
 void
985021
 info_terminal_command (const char *arg, int from_tty)
985021
 {
985021
diff --git a/gdb/infrun.c b/gdb/infrun.c
985021
--- a/gdb/infrun.c
985021
+++ b/gdb/infrun.c
985021
@@ -1197,12 +1197,14 @@ follow_exec (ptid_t ptid, char *exec_file_target)
985021
       /* The user wants to keep the old inferior and program spaces
985021
 	 around.  Create a new fresh one, and switch to it.  */
985021
 
985021
-      /* Do exit processing for the original inferior before adding
985021
-	 the new inferior so we don't have two active inferiors with
985021
-	 the same ptid, which can confuse find_inferior_ptid.  */
985021
+      /* Do exit processing for the original inferior before setting the new
985021
+	 inferior's pid.  Having two inferiors with the same pid would confuse
985021
+	 find_inferior_p(t)id.  Transfer the terminal state and info from the
985021
+	  old to the new inferior.  */
985021
+      inf = add_inferior_with_spaces ();
985021
+      swap_terminal_info (inf, current_inferior ());
985021
       exit_inferior_silent (current_inferior ());
985021
 
985021
-      inf = add_inferior_with_spaces ();
985021
       inf->pid = pid;
985021
       target_follow_exec (inf, exec_file_target);
985021
 
985021
diff --git a/gdb/terminal.h b/gdb/terminal.h
985021
--- a/gdb/terminal.h
985021
+++ b/gdb/terminal.h
985021
@@ -29,6 +29,9 @@ extern void new_tty_postfork (void);
985021
 
985021
 extern void copy_terminal_info (struct inferior *to, struct inferior *from);
985021
 
985021
+/* Exchange the terminal info and state between inferiors A and B.  */
985021
+extern void swap_terminal_info (inferior *a, inferior *b);
985021
+
985021
 extern pid_t create_tty_session (void);
985021
 
985021
 /* Set up a serial structure describing standard input.  In inflow.c.  */