gdb: move setbuf calls out of gdb_readline_no_editing_callback

After this commit:

  commit d08cbc5d32
  Date:   Wed Dec 22 12:57:44 2021 +0000

      gdb: unbuffer all input streams when not using readline

Issues were reported with some MS-Windows hosts, see the thread
starting here:

  https://sourceware.org/pipermail/gdb-patches/2022-March/187004.html

Filed in bugzilla as: PR mi/29002

The problem seems to be that calling setbuf on terminal file handles
is not always acceptable, see this mail for more details:

  https://sourceware.org/pipermail/gdb-patches/2022-April/187310.html

This commit does two things, first moving the setbuf calls out of
gdb_readline_no_editing_callback so that we don't end up calling
setbuf so often.

Then, for MS-Windows hosts, we don't call setbuf for terminals, this
appears to resolve the issues that have been reported.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29002
This commit is contained in:
Andrew Burgess 2022-04-24 08:39:19 -07:00 committed by Joel Brobecker
parent 69be4d89e3
commit ac16b09d7e
2 changed files with 39 additions and 13 deletions

View File

@ -863,19 +863,6 @@ gdb_readline_no_editing_callback (gdb_client_data client_data)
FILE *stream = ui->instream != nullptr ? ui->instream : ui->stdin_stream;
gdb_assert (stream != nullptr);
/* Unbuffer the input stream, so that, later on, the calls to fgetc
fetch only one char at the time from the stream. The fgetc's will
get up to the first newline, but there may be more chars in the
stream after '\n'. If we buffer the input and fgetc drains the
stream, getting stuff beyond the newline as well, a select, done
afterwards will not trigger.
This unbuffering was, at one point, not applied if the input stream
was a tty, however, the buffering can cause problems, even for a tty,
in some cases. Please ensure that any changes in this area run the MI
tests with the FORCE_SEPARATE_MI_TTY=1 flag being passed. */
setbuf (stream, NULL);
/* We still need the while loop here, even though it would seem
obvious to invoke gdb_readline_no_editing_callback at every
character entered. If not using the readline library, the

View File

@ -257,6 +257,41 @@ void (*deprecated_context_hook) (int id);
/* The highest UI number ever assigned. */
static int highest_ui_num;
/* Unbuffer STREAM. This is a wrapper around setbuf(STREAM, nullptr)
which applies some special rules for MS-Windows hosts. */
static void
unbuffer_stream (FILE *stream)
{
/* Unbuffer the input stream so that in gdb_readline_no_editing_callback,
the calls to fgetc fetch only one char at the time from STREAM.
This is important because gdb_readline_no_editing_callback will read
from STREAM up to the first '\n' character, after this GDB returns to
the event loop and relies on a select on STREAM indicating that more
input is pending.
If STREAM is buffered then the fgetc calls may have moved all the
pending input from the kernel into a local buffer, after which the
select will not indicate that more input is pending, and input after
the first '\n' will not be processed immediately.
Please ensure that any changes in this area run the MI tests with the
FORCE_SEPARATE_MI_TTY=1 flag being passed. */
#ifdef __MINGW32__
/* With MS-Windows runtime, making stdin unbuffered when it's
connected to the terminal causes it to misbehave. */
if (!ISATTY (stream))
setbuf (stream, nullptr);
#else
/* On GNU/Linux the issues described above can impact GDB even when
dealing with input from a terminal. For now we unbuffer the input
stream for everyone except MS-Windows. */
setbuf (stream, nullptr);
#endif
}
/* See top.h. */
ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
@ -283,6 +318,8 @@ ui::ui (FILE *instream_, FILE *outstream_, FILE *errstream_)
{
buffer_init (&line_buffer);
unbuffer_stream (instream_);
if (ui_list == NULL)
ui_list = this;
else
@ -412,6 +449,8 @@ read_command_file (FILE *stream)
{
struct ui *ui = current_ui;
unbuffer_stream (stream);
scoped_restore save_instream
= make_scoped_restore (&ui->instream, stream);