[newlib-cygwin] Cygwin: console: Fix regression in console input
Takashi Yano via Cygwin-cvs <[email protected]>
| Newsgroups | gmane.os.cygwin.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=9807479c90e37913900569d3a8f3b10247bf7860 commit 9807479c90e37913900569d3a8f3b10247bf7860 Author: Takashi Yano <[email protected]> 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 <[email protected]> Fixes: fac73911f5a0 ("Cygwin: console: Fix typeahead input for bash") Signed-off-by: Takashi Yano <[email protected]> Revewied-by: Johannes Schindelin <[email protected]> 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; }