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

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