diff --git a/SOURCES/_gdb.spec.Patch.include b/SOURCES/_gdb.spec.Patch.include index 49428b9..cdcadc2 100644 --- a/SOURCES/_gdb.spec.Patch.include +++ b/SOURCES/_gdb.spec.Patch.include @@ -807,3 +807,11 @@ Patch197: gdb-rhbz2012818-ibmz-update-5of5.patch # (Jozef Lawrynowicz, RHBZ 2018504) Patch198: gdb-rhbz2018504-do-not-update-elf-headers.patch +# Fix restoring of inferior terminal settings +# (Simon Marchi, RHBZ 2015131) +Patch199: gdb-rhbz2015131-restore-inferior-terminal-1of2.patch + +# Avoid GDB SIGTTOU on catch exec + set follow-exec-mode new (PR 23368) +# (Simon Marchi, related to RHBZ 2015131) +Patch200: gdb-rhbz2015131-avoid-sigttou-forks-2of2.patch + diff --git a/SOURCES/_gdb.spec.patch.include b/SOURCES/_gdb.spec.patch.include index c1d18ac..eba9d45 100644 --- a/SOURCES/_gdb.spec.patch.include +++ b/SOURCES/_gdb.spec.patch.include @@ -196,3 +196,5 @@ %patch196 -p1 %patch197 -p1 %patch198 -p1 +%patch199 -p1 +%patch200 -p1 diff --git a/SOURCES/gdb-rhbz2015131-avoid-sigttou-forks-2of2.patch b/SOURCES/gdb-rhbz2015131-avoid-sigttou-forks-2of2.patch new file mode 100644 index 0000000..7cfe4be --- /dev/null +++ b/SOURCES/gdb-rhbz2015131-avoid-sigttou-forks-2of2.patch @@ -0,0 +1,115 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Simon Marchi +Date: Tue, 23 Oct 2018 17:00:33 -0400 +Subject: gdb-rhbz2015131-avoid-sigttou-forks-2of2.patch + +;; Avoid GDB SIGTTOU on catch exec + set follow-exec-mode new (PR 23368) +;; (Simon Marchi, related to RHBZ 2015131) + +Here's a summary of PR 23368: + + #include + 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. + +diff --git a/gdb/inflow.c b/gdb/inflow.c +--- a/gdb/inflow.c ++++ b/gdb/inflow.c +@@ -671,6 +671,22 @@ copy_terminal_info (struct inferior *to, struct inferior *from) + to->terminal_state = from->terminal_state; + } + ++/* See terminal.h. */ ++ ++void ++swap_terminal_info (inferior *a, inferior *b) ++{ ++ terminal_info *info_a ++ = (terminal_info *) inferior_data (a, inflow_inferior_data); ++ terminal_info *info_b ++ = (terminal_info *) inferior_data (a, inflow_inferior_data); ++ ++ set_inferior_data (a, inflow_inferior_data, info_b); ++ set_inferior_data (b, inflow_inferior_data, info_a); ++ ++ std::swap (a->terminal_state, b->terminal_state); ++} ++ + void + info_terminal_command (const char *arg, int from_tty) + { +diff --git a/gdb/infrun.c b/gdb/infrun.c +--- a/gdb/infrun.c ++++ b/gdb/infrun.c +@@ -1197,12 +1197,14 @@ follow_exec (ptid_t ptid, char *exec_file_target) + /* The user wants to keep the old inferior and program spaces + around. Create a new fresh one, and switch to it. */ + +- /* Do exit processing for the original inferior before adding +- the new inferior so we don't have two active inferiors with +- the same ptid, which can confuse find_inferior_ptid. */ ++ /* Do exit processing for the original inferior before setting the new ++ inferior's pid. Having two inferiors with the same pid would confuse ++ find_inferior_p(t)id. Transfer the terminal state and info from the ++ old to the new inferior. */ ++ inf = add_inferior_with_spaces (); ++ swap_terminal_info (inf, current_inferior ()); + exit_inferior_silent (current_inferior ()); + +- inf = add_inferior_with_spaces (); + inf->pid = pid; + target_follow_exec (inf, exec_file_target); + +diff --git a/gdb/terminal.h b/gdb/terminal.h +--- a/gdb/terminal.h ++++ b/gdb/terminal.h +@@ -29,6 +29,9 @@ 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. */ diff --git a/SOURCES/gdb-rhbz2015131-restore-inferior-terminal-1of2.patch b/SOURCES/gdb-rhbz2015131-restore-inferior-terminal-1of2.patch new file mode 100644 index 0000000..0502747 --- /dev/null +++ b/SOURCES/gdb-rhbz2015131-restore-inferior-terminal-1of2.patch @@ -0,0 +1,201 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Simon Marchi +Date: Wed, 22 Aug 2018 11:09:45 -0400 +Subject: gdb-rhbz2015131-restore-inferior-terminal-1of2.patch + +;; Fix restoring of inferior terminal settings +;; (Simon Marchi, RHBZ 2015131) + +I noticed that the child_terminal_save_inferior function was not used +since the commit f6ac5f3d63e0 ("Convert struct target_ops to C++"). I +was able to make a little test program to illustrate the problem (see +test case). + +I think we're just missing the override of the terminal_save_inferior +method in inf_child_target (along with the other terminal-related +methods). + +Instead of creating a new test, I thought that gdb.base/term.exp was a +good candidate for testing that gdb restores properly the inferior's +terminal settings. + +gdb/ChangeLog: + + * inf-child.h (inf_child_target) : New. + * inf-child.c (inf_child_target::terminal_save_inferior): New. + +gdb/testsuite/ChangeLog: + + * gdb.base/term.exp: Compare terminal settings with values from + the inferior. + * gdb.base/term.c: Get and set terminal settings. + +diff --git a/gdb/inf-child.c b/gdb/inf-child.c +--- a/gdb/inf-child.c ++++ b/gdb/inf-child.c +@@ -113,6 +113,12 @@ inf_child_target::terminal_inferior () + child_terminal_inferior (this); + } + ++void ++inf_child_target::terminal_save_inferior () ++{ ++ child_terminal_save_inferior (this); ++} ++ + void + inf_child_target::terminal_ours_for_output () + { +diff --git a/gdb/inf-child.h b/gdb/inf-child.h +--- a/gdb/inf-child.h ++++ b/gdb/inf-child.h +@@ -46,6 +46,7 @@ public: + bool supports_terminal_ours () override; + void terminal_init () override; + void terminal_inferior () override; ++ void terminal_save_inferior () override; + void terminal_ours_for_output () override; + void terminal_ours () override; + void terminal_info (const char *, int) override; +diff --git a/gdb/testsuite/gdb.base/term.c b/gdb/testsuite/gdb.base/term.c +--- a/gdb/testsuite/gdb.base/term.c ++++ b/gdb/testsuite/gdb.base/term.c +@@ -15,7 +15,29 @@ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + ++#include ++#include ++ ++static struct termios t; ++ ++static void ++break_here () ++{ ++} ++ + int main () + { ++ tcgetattr (0, &t); ++ break_here (); ++ ++ /* Disable ECHO. */ ++ t.c_lflag &= ~ECHO; ++ tcsetattr (0, TCSANOW, &t); ++ tcgetattr (0, &t); ++ break_here (); ++ ++ tcgetattr (0, &t); ++ break_here (); ++ + return 0; + } +diff --git a/gdb/testsuite/gdb.base/term.exp b/gdb/testsuite/gdb.base/term.exp +--- a/gdb/testsuite/gdb.base/term.exp ++++ b/gdb/testsuite/gdb.base/term.exp +@@ -13,6 +13,9 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + ++# Test that GDB saves and restores terminal settings correctly. Also check ++# the output of the "info terminal" command. ++ + if { [prepare_for_testing "failed to prepare" term term.c] } { + return -1 + } +@@ -20,28 +23,84 @@ if { [prepare_for_testing "failed to prepare" term term.c] } { + # Once before running the program. + gdb_test "info terminal" \ + "No saved terminal information.*" \ +- "test info terminal" ++ "test info terminal pre-execution" + +-if ![runto_main] then { +- fail "can't run to main" ++if ![runto break_here] then { ++ fail "can't run to break_here" + return 0 + } + +-# Once while the program is running and stopped. ++# Read the inferior's terminal settings, saved in the T global variable. ++ ++proc read_term_settings_from_inferior {} { ++ set termios(c_iflag) [get_hexadecimal_valueof "t.c_iflag" oops] ++ set termios(c_oflag) [get_hexadecimal_valueof "t.c_oflag" oops] ++ set termios(c_cflag) [get_hexadecimal_valueof "t.c_cflag" oops] ++ set termios(c_lflag) [get_hexadecimal_valueof "t.c_lflag" oops] ++ ++ return [array get termios] ++} ++ ++# Validate that gdb's notion of the inferior's terminal settings are consistent ++# with the values read from the inferior. ++ ++proc compare_gdb_and_inferior_settings { t } { ++ global decimal ++ array set termios $t ++ ++ gdb_test "info terminal" \ ++ [multi_line "Inferior's terminal status .currently saved by GDB.:" \ ++ "File descriptor flags = .*" \ ++ "Process group = $decimal" \ ++ "c_iflag = ${termios(c_iflag)}, c_oflag = ${termios(c_oflag)}," \ ++ "c_cflag = ${termios(c_cflag)}, c_lflag = ${termios(c_lflag)}.*" ] ++} + +-# While only native targets save terminal status, we still test +-# everywhere to make sure that the command doesn't misbehave. + if {[target_info gdb_protocol] == ""} { +- set term_re "Inferior's terminal status .currently saved by GDB.:.*" ++ # Record the initial terminal settings. Verify that GDB's version of the ++ # inferior's terminal settings is right. ++ with_test_prefix "initial" { ++ array set termios1 [read_term_settings_from_inferior] ++ compare_gdb_and_inferior_settings [array get termios1] ++ } ++ ++ # Continue until after the inferior removes ECHO from its terminal settings. ++ gdb_continue_to_breakpoint "continue until after tcsetattr" ++ ++ # After the inferior has changed its terminal settings, check that GDB's ++ # saved version reflects the new settings correctly. ++ with_test_prefix "post tcsetattr" { ++ array set termios2 [read_term_settings_from_inferior] ++ compare_gdb_and_inferior_settings [array get termios2] ++ ++ # Make sure that the current settings are different than the initial ++ # settings... otherwise this test is meaningless. ++ gdb_assert {${termios1(c_lflag)} != ${termios2(c_lflag)}} ++ } ++ ++ # Continue again... ++ gdb_continue_to_breakpoint "continue again" ++ ++ # ... and verify again, to validate that when resuming, GDB restored the ++ # inferior's terminal settings correctly. ++ with_test_prefix "after last resume" { ++ array set termios3 [read_term_settings_from_inferior] ++ compare_gdb_and_inferior_settings [array get termios3] ++ gdb_assert {${termios2(c_iflag)} == ${termios3(c_iflag)}} ++ gdb_assert {${termios2(c_oflag)} == ${termios3(c_oflag)}} ++ gdb_assert {${termios2(c_cflag)} == ${termios3(c_cflag)}} ++ gdb_assert {${termios2(c_lflag)} == ${termios3(c_lflag)}} ++ } + } else { +- set term_re "No saved terminal information\\." ++ # While only native targets save terminal status, we still test ++ # that the command doesn't misbehave. ++ gdb_test "info terminal" "No saved terminal information\\." "info terminal at breakpoint" + } + +-gdb_test "info terminal" $term_re "info terminal at breakpoint" +- ++delete_breakpoints + gdb_continue_to_end + + # One last time after the program having exited. + gdb_test "info terminal" \ + "No saved terminal information.*" \ +- "test info terminal #2" ++ "test info terminal post-execution" diff --git a/SPECS/gdb.spec b/SPECS/gdb.spec index 7da614e..2806f06 100644 --- a/SPECS/gdb.spec +++ b/SPECS/gdb.spec @@ -26,7 +26,7 @@ Version: 8.2 # The release always contains a leading reserved number, start it at 1. # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. -Release: 18%{?dist} +Release: 19%{?dist} License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and LGPLv3+ and BSD and Public Domain and GFDL Group: Development/Debuggers @@ -1062,6 +1062,12 @@ fi %endif %changelog +* Tue May 24 2022 Keith Seitz - 8.2-19.el8 +- Backport "Fix restoring of inferior terminal settings" +- Backport "Avoid GDB SIGTTOU on catch exec + set follow-exec-mode + new (PR 23368)" + (Simon Marchi, RH BZ 2015131) + * Wed Dec 8 2021 Keith Seitz - 8.2-18.el8 - Backport "Fix avx512 -m32 support in gdbserver" - (Tom de Vries, RH BZ 2011520)