[newlib-cygwin] Cygwin: console: Fix regression in console input
Takashi Yano
tyan0@sourceware.org
Thu Aug 6 16:07:20 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=9807479c90e37913900569d3a8f3b10247bf7860
commit 9807479c90e37913900569d3a8f3b10247bf7860
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date: Mon Aug 3 10:41:14 2026 +0900
Cygwin: console: Fix regression in console input
The commit fac73911f5a0 ("Cygwin: console: Fix typeahead input for
bash") introduced a bug where select() consumes some input chars in
canonical mode, preventing read() from reading them. This is due to
discarding input events when process_input_message() does not return
`input_ok` even if it is called from select().
The basic idea of that commit was making process_input_message()
not to store processed chars into readahead buffer. This was not
correct because the key input events were processed twice, once by
select() and again by read(). Thus even if that commit worked as
intended, the side effect such as input echo would be applied twice.
With this patch, process_input_message() handles only the minimum
necessary of input events in both cases, those processed by select()
and those processed by read(). To achieve this behaviour, the function
returns without processing when `input_ready` is already satisfied,
or after it has processed the specified number of chars.
Addresses: https://cygwin.com/pipermail/cygwin/2026-August/259915.html
Reported-by: Steven Doerfler <sgd-cygwinlist@lugaru.com>
Fixes: fac73911f5a0 ("Cygwin: console: Fix typeahead input for bash")
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Revewied-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Diff:
---
winsup/cygwin/fhandler/console.cc | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index d4c87f29f..ba35ca44c 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -479,7 +479,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
}
WaitForSingleObject (p->input_mutex, mutex_timeout);
- /* Ensure accessing input recored is not disabled. */
+ /* Ensure accessing input record is not disabled. */
if (con.disable_master_thread)
{
ReleaseMutex (p->input_mutex);
@@ -1331,7 +1331,6 @@ fhandler_console::input_states
fhandler_console::process_input_message (size_t len)
{
char tmp[60];
- size_t num_chars = 0;
if (!shared_console_info[unit])
return input_error;
@@ -1354,6 +1353,13 @@ fhandler_console::process_input_message (size_t len)
return input_error;
}
+ /* len == 0 if called from select.cc:peek_console() */
+ /* This code is reached only when being passed the input_ready check,
+ however, the check was done outside input_mutex. Therefore, another
+ thread may set input_ready after the check. Check it again here. */
+ if (input_ready && (len == 0 || (get_ttyp ()->ti.c_lflag & ICANON)))
+ return input_ok;
+
for (i = 0; i < total_read; i ++)
{
DWORD nread = 1;
@@ -1719,7 +1725,6 @@ fhandler_console::process_input_message (size_t len)
}
num_input_events_processed = i + 1;
- num_chars += nread;
if (toadd)
{
ssize_t ret;
@@ -1738,21 +1743,17 @@ fhandler_console::process_input_message (size_t len)
}
}
/* len == 0 if called from select.cc:peek_console() */
- if (len && num_chars >= len)
+ if (input_ready && (len == 0 || con_ra.ralen >= len))
goto out;
}
out:
- if (len == 0)
- /* If len == 0, cancel reading from console input buffer.
- Clear readahead buffer. */
- eat_readahead (-1);
- /* Discard processed recored. */
+ /* Discard processed record. */
DWORD discard_len = min (total_read, i + 1);
/* If input is signalled, do not discard input here because
discard_key_events() is already called from line_edit(). */
if (stat == input_signalled)
discard_len = 0;
- if (discard_len && (len || stat != input_ok))
+ if (discard_len)
discard_key_events (discard_len);
return stat;
}
More information about the Cygwin-cvs
mailing list