[PATCH] Cygwin: console: Fix regression in console input
Takashi Yano <[email protected]> Mon, 3 Aug 2026 11:49:59 +0900
| Newsgroups | gmane.os.cygwin.patches |
|---|---|
| Message-ID | <[email protected]> |
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 ware 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 achive 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 <[email protected]>
Fixes: fac73911f5a0 ("Cygwin: console: Fix typeahead input for bash")
Signed-off-by: Takashi Yano <[email protected]>
Revewed-by:
---
winsup/cygwin/fhandler/console.cc | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index 0219a37ef..3904fbd57 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -1406,7 +1406,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;
@@ -1429,6 +1428,10 @@ fhandler_console::process_input_message (size_t len)
return input_error;
}
+ /* len == 0 if called from select.cc:peek_console() */
+ if (input_ready && (len == 0 || (get_ttyp ()->ti.c_lflag & ICANON)))
+ return input_ok;
+
for (i = 0; i < total_read; i ++)
{
DWORD nread = 1;
@@ -1794,7 +1797,6 @@ fhandler_console::process_input_message (size_t len)
}
num_input_events_processed = i + 1;
- num_chars += nread;
if (toadd)
{
ssize_t ret;
@@ -1813,21 +1815,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. */
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;
}
--
2.51.0