|
|
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. */
|