gdb/tui: install SIGWINCH only when connected to a TTY
authorLancelot SIX <lancelot.six@amd.com>
Mon, 13 Dec 2021 13:48:48 +0000 (07:48 -0600)
committerLancelot SIX <lancelot.six@amd.com>
Fri, 17 Dec 2021 08:56:25 +0000 (03:56 -0500)
commit72994b6028360eccb5d25b39d2e18b386d091426
tree855d88a99f9ca5ddc6110d496f1a2d29e0a5e3bf
parent27e3da31c31572fde3d6e244a68ea45fb874b038
gdb/tui: install SIGWINCH only when connected to a TTY

PR26056 reports that when GDB is connected to non-TTY stdin/stdout, it
crashes when it receives a SIGWINCH signal.

This can be reproduced as follows:

    $ gdb/gdb -nx -batch -ex 'run' --args sleep 60 </dev/null 2>&1 | cat

    # from another terminal:
    $ kill -WINCH %(pidof gdb)

When doing so, the process crashes in a call to rl_resize_terminal:

    void
    rl_resize_terminal (void)
    {
      _rl_get_screen_size (fileno (rl_instream), 1);
      ...
    }

The problem is that at this point rl_instream has the value NULL.

The rl_instream variable is supposed to be initialized during a call to
readline_initialize_everything, which in a normal startup sequence is
called under this call chain:

    tui_interp::init
      tui_ensure_readline_initialized
        rl_initialize
          readline_initialize_everything

In tui_interp::init, we have the following sequence:

    tui_initialize_io ();
    tui_initialize_win ();                // <- Installs SIGWINCH
    if (gdb_stdout->isatty ())
      tui_ensure_readline_initialized (); // <- Initializes rl_instream

This function unconditionally installs the SIGWINCH signal handler (this
is done by tui_initialize_win), and then if gdb_stdout is a TTY it
initializes readline.  Therefore, if stdout is not a TTY, SIGWINCH is
installed but readline is not initialized.  In such situation
rl_instream stays NULL, and when GDB receives a SIGWINCH it calls its
handler and in fine tries to access rl_instream leading to the crash.

This patch proposes to fix this issue by installing the SIGWINCH signal
handler only if GDB is connected to a TTY.  Given that this
initialization it the only task of tui_initialize_win, this patch moves
tui_initialize_win just after the call to
tui_ensure_readline_initialized.

Tested on x86_64-linux.

Co-authored-by: Pedro Alves <pedro@palves.net>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=26056
Change-Id: I6458acef7b0d9beda2a10715d0345f02361076d9
gdb/testsuite/gdb.base/sigwinch-notty.exp [new file with mode: 0644]
gdb/testsuite/lib/gdb.exp
gdb/testsuite/lib/notty-wrap [new file with mode: 0755]
gdb/tui/tui-interp.c