From: Andrew Burgess Date: Fri, 12 Dec 2025 11:27:53 +0000 (+0000) Subject: gdb: fix crash from 'shell' when GDB has no terminal X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99c0793e90539a318d7aa437615bc0e271db8935;p=thirdparty%2Fbinutils-gdb.git gdb: fix crash from 'shell' when GDB has no terminal Bug PR gdb/33716 identifies a problem where GDB will crash when using the 'shell' command if GDB is not attached to a terminal. E.g.: $ gdb -nw -nh -q -batch -ex 'shell echo hello' --- diff --git a/gdb/inflow.c b/gdb/inflow.c index 518b2dcf4e0..0292192ae2e 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -49,6 +49,8 @@ static void pass_signal (int); +static int gdb_has_a_terminal (void); + static void child_terminal_ours_1 (target_terminal_state); /* Record terminal status separately for debugger and inferior. */ @@ -59,14 +61,16 @@ static struct serial *stdin_serial; scoped_restore_tty_state::scoped_restore_tty_state () { - m_ttystate = serial_get_tty_state (stdin_serial); + if (gdb_has_a_terminal ()) + m_ttystate = serial_get_tty_state (stdin_serial); } /* See terminal.h. */ scoped_restore_tty_state::~scoped_restore_tty_state () { - serial_set_tty_state (stdin_serial, m_ttystate); + if (m_ttystate != nullptr) + serial_set_tty_state (stdin_serial, m_ttystate); } /* Terminal related info we need to keep track of. Each inferior diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index f9ef8441629..9d17e1cc3ad 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -152,6 +152,7 @@ hardwire_set_tty_state (struct serial *scb, serial_ttystate ttystate) struct hardwire_ttystate *state; state = (struct hardwire_ttystate *) ttystate; + gdb_assert (state != nullptr); return set_tty_state (scb, state); } diff --git a/gdb/serial.h b/gdb/serial.h index 6bcb5ab6598..b974491933c 100644 --- a/gdb/serial.h +++ b/gdb/serial.h @@ -152,7 +152,8 @@ extern void serial_send_break (struct serial *scb); extern void serial_raw (struct serial *scb); /* Return a pointer to a newly malloc'd ttystate containing the state - of the tty. */ + of the tty. Can return NULL if the current tty state could not be + read, for example, if GDB's stdin is not a terminal. */ extern serial_ttystate serial_get_tty_state (struct serial *scb); diff --git a/gdb/terminal.h b/gdb/terminal.h index 225554a60c3..892d43113d4 100644 --- a/gdb/terminal.h +++ b/gdb/terminal.h @@ -59,7 +59,9 @@ public: DISABLE_COPY_AND_ASSIGN (scoped_restore_tty_state); private: - serial_ttystate m_ttystate; + /* The saved tty state. This can remain NULL even after the constructor + has run if serial_get_tty_state fails to fetch the tty state. */ + serial_ttystate m_ttystate = nullptr; }; #ifdef USE_WIN32API diff --git a/gdb/testsuite/gdb.base/shell-no-terminal.exp b/gdb/testsuite/gdb.base/shell-no-terminal.exp new file mode 100644 index 00000000000..2a630fb1541 --- /dev/null +++ b/gdb/testsuite/gdb.base/shell-no-terminal.exp @@ -0,0 +1,60 @@ +# Copyright 2025 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Run GDB in batch mode, with stdin attached to a non-pty. Use the +# 'shell' command from the GDB command line. Check that GDB doesn't +# crash. This checks for bug PR gdb/33716. + +# Remote boards override the 'remote_spawn' mechanism, and don't +# support the 'readonly' argument that this test relies on. Just +# running this test on local hosts should be fine. +require {!is_remote host} + +gdb_exit + +save_vars { GDBFLAGS } { + append GDBFLAGS " -batch -ex \"shell echo first\" -ex \"shell echo second\"