From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7868) id 5DC943858D3C; Fri, 18 Mar 2022 13:48:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5DC943858D3C Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Takashi Yano To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin/cygwin-3_3-branch] Cygwin: console: Fix typeahead key swapping which still occurs. X-Act-Checkin: newlib-cygwin X-Git-Author: Takashi Yano X-Git-Refname: refs/heads/cygwin-3_3-branch X-Git-Oldrev: 8dd9b119906ed214f600088743e6b52c6d1bf254 X-Git-Newrev: 4be4da65efbfb7656cdcab2bfcaff1d7b068a8c6 Message-Id: <20220318134819.5DC943858D3C@sourceware.org> Date: Fri, 18 Mar 2022 13:48:19 +0000 (GMT) X-BeenThere: cygwin-cvs@cygwin.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Cygwin core component git logs List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 18 Mar 2022 13:48:19 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D4be4da65efb= fb7656cdcab2bfcaff1d7b068a8c6 commit 4be4da65efbfb7656cdcab2bfcaff1d7b068a8c6 Author: Takashi Yano Date: Fri Mar 18 21:35:07 2022 +0900 Cygwin: console: Fix typeahead key swapping which still occurs. =20 - The commit "Cygwin: console: Improve the code to avoid typeahead key swapping." did not solve the problem enough. Two unexpected things happen. (1) wVirtualKeyCode and wVirtualScanCode of readback key event may be null'ed even if they are not zero on WriteConsoleInputW(). Therefore, memcmp() may report the event sequence is not equal. (2) WriteConsoleInputW() may not be atomic. The event sequence which is written by WriteConsoleInputW() may be inserted by key input in the middle of the sequence. Current code gives up to fix in this situation. This patch should fix that issue. Diff: --- winsup/cygwin/fhandler_console.cc | 58 +++++++++++++++++++++++++----------= ---- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_con= sole.cc index e43d2ac14..b52ecfca6 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -180,6 +180,29 @@ cons_master_thread (VOID *arg) return 0; } =20 +/* Compare two INPUT_RECORD sequences */ +static inline bool +inrec_eq (const INPUT_RECORD *a, const INPUT_RECORD *b, DWORD n) +{ + for (DWORD i =3D 0; i < n; i++) + { + if (a[i].EventType =3D=3D KEY_EVENT && b[i].EventType =3D=3D KEY_EVE= NT) + { /* wVirtualKeyCode and wVirtualScanCode of the readback + key event may be different from that of written event. */ + const KEY_EVENT_RECORD *ak =3D &a[i].Event.KeyEvent; + const KEY_EVENT_RECORD *bk =3D &b[i].Event.KeyEvent; + if (ak->bKeyDown !=3D bk->bKeyDown + || ak->uChar.UnicodeChar !=3D bk->uChar.UnicodeChar + || ak->dwControlKeyState !=3D bk->dwControlKeyState + || ak->wRepeatCount !=3D bk->wRepeatCount) + return false; + } + else if (memcmp (a + i, b + i, sizeof (INPUT_RECORD)) !=3D 0) + return false; + } + return true; +} + /* This thread processes signals derived from input messages. Without this thread, those signals can be handled only when the process calls read() or select(). This thread reads input @@ -327,30 +350,25 @@ remove_record: if (n < total_read) break; /* Someone has read input without acquiring input_mutex. ConEmu cygwin-connector? */ - if (memcmp (input_rec, tmp, m.bytes (total_read)) =3D=3D 0) + if (inrec_eq (input_rec, tmp, total_read)) break; /* OK */ /* Try to fix */ - DWORD incr =3D n - total_read; - DWORD ofst; - for (ofst =3D 1; ofst <=3D incr; ofst++) - if (memcmp (input_rec, tmp + ofst, m.bytes (total_read)) =3D=3D 0) + acquire_attach_mutex (mutex_timeout); + ReadConsoleInputW (p->input_handle, tmp, inrec_size, &n); + release_attach_mutex (); + for (DWORD i =3D 0, j =3D 0; j < n; j++) + if (i =3D=3D total_read || !inrec_eq (input_rec + i, tmp + j, 1)) { - acquire_attach_mutex (mutex_timeout); - ReadConsoleInputW (p->input_handle, tmp, inrec_size, &n); - release_attach_mutex (); - memcpy (input_rec, tmp + ofst, m.bytes (total_read)); - memcpy (input_rec + total_read, tmp, m.bytes (ofst)); - if (n > ofst + total_read) - memcpy (input_rec + total_read + ofst, - tmp + ofst + total_read, - m.bytes (n - (ofst + total_read))); - total_read =3D n; - break; + if (total_read + j - i >=3D n) + { /* Something is wrong. Giving up. */ + WriteConsoleInputW (p->input_handle, tmp, n, &n); + goto skip_writeback; + } + input_rec[total_read + j - i] =3D tmp[j]; } - if (ofst > incr) - break; /* Writeback was not atomic. Or someone has read - input without acquiring input_mutex. - Giving up because hard to fix. */ + else + i++; + total_read =3D n; } while (true); }