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

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