On Thu, 17 Mar 2022 20:40:15 +0200 Orgad Shaneh wrote: > On Fri, Mar 11, 2022 at 11:36 PM Takashi Yano <takashi.y...@nifty.ne.jp> > wrote: > > I looked into this problem and found the cause. > > This seems to be due to a bug of fsync(). Cygwin's fsync() > > flushes the console input buffer unlike linux. > > > > I will propose a patch for this issue. > > > > -- > > Takashi Yano <takashi.y...@nifty.ne.jp> > > Thank you very much. Looks better now. > > I'm sorry for nudging, but on msys2 I still get frequent mistypes when > typing fast. > > I (still) don't have a consistent reproduction, but if I get it > correctly, it looks like one or more characters I type right when the > prompt appears show up before the buffered characters. > > For instance, I run git fetch, and while it is running I type git > status, *sometimes* 1-2 characters "pop" to the left, so I get > something like tgit satus. > > I wasn't able to reproduce it with cygwin, but on msys2 (with cygwin > 3.3 branch merged in) it happens to me all the time :/
Thansk for the report. I cloned the msys2-runtime repository from https://github.com/msys2/msys2-runtime and applied patches in cygwin-3_3-branch against msys2-3_3_4-release branch. The patches applied are listed in cygwin-3_3-branch-merged.log attached. A few patches, which are not actually in cygwin-3_3-branch, are also applied just for avoiding conflict easily. However, I cannot reproduce your problem. Have you surely applied the following patches especially important for this issue? Could you please also check if the code of cons_master_thread() in fhandler_console.cc exactly matches with cons_master_thread.cc attached? commit 4d0721a66f94427fa14601d0c58a0762709b5bf2 Author: Takashi Yano <takashi.y...@nifty.ne.jp> Date: Fri Feb 25 17:10:03 2022 +0900 Cygwin: console: Prevent the order of typeahead input from swapped. - If a lot of keys are typed very quickly in the app which does not read console, the order of input keys in console input buffer occasionally swapped. Although this extremely rarely happens, is obviously a bug of cons_master_thread. This patch fixes the issue. commit f48870148c7ebcaf8163b08a040d15ef048f4e94 Author: Takashi Yano <takashi.y...@nifty.ne.jp> Date: Mon Feb 28 20:02:01 2022 +0900 Cygwin: console: Improve the code to avoid typeahead key swapping. - The commit "Cygwin: console: Prevent the order of typeahead input from swapped." did not fully resolve the issue. If keys are typed during input buffer fix, the order of key event may be swapped. This patch fixes the issue again. commit 6e872adb9f153ba0504c898a91ac8dcf0ed7e68a Author: Takashi Yano <takashi.y...@nifty.ne.jp> Date: Wed Mar 2 09:55:52 2022 +0900 Cygwin: console: Prevent special keys processing from drop. - There was a potential risk to drop special key processing when process_input_messsage() is called intermittently. This patch fixes the issue. commit d88768187a72662d1692ee279e7dea3e948d256e Author: Takashi Yano <takashi.y...@nifty.ne.jp> Date: Wed Mar 2 11:08:27 2022 +0900 Cygwin: console: Fix a bug from comparison between int and DWORD. commit cef38f41f2ce0510855bb4b872c7f6514f6deca5 Author: Takashi Yano <takashi.y...@nifty.ne.jp> Date: Wed Mar 2 16:00:31 2022 +0900 Cygwin: console, pty: Revamp the acquire/release_attach_mutex timing. - This patch revises the acquiring/releasing timing for attach_mutex to make the period in which it is being acquired shorter. Further, acquiring/releasing are added to where they are missing but needed. -- Takashi Yano <takashi.y...@nifty.ne.jp>
cygwin-3_3-branch-merged.log
Description: Binary data
/* 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 records, processes signals and removes corresponding record. The other input records are kept back for read() or select(). */ void fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) { const int additional_space = 128; /* Possible max number of incoming events during the process. Additional space should be left for writeback fix. */ const int inrec_size = INREC_SIZE + additional_space; struct m { inline static size_t bytes (size_t n) { return sizeof (INPUT_RECORD) * n; } }; termios &ti = ttyp->ti; while (con.owner == myself->pid) { DWORD total_read, n, i; INPUT_RECORD input_rec[inrec_size]; if (con.disable_master_thread) { cygwait (40); continue; } WaitForSingleObject (p->input_mutex, mutex_timeout); total_read = 0; bool nowait = false; switch (cygwait (p->input_handle, (DWORD) 0)) { case WAIT_OBJECT_0: acquire_attach_mutex (mutex_timeout); ReadConsoleInputW (p->input_handle, input_rec, INREC_SIZE, &total_read); if (total_read == INREC_SIZE /* Working space full */ && cygwait (p->input_handle, (DWORD) 0) == WAIT_OBJECT_0) { const int incr = min (con.num_processed, additional_space); ReadConsoleInputW (p->input_handle, input_rec + total_read, incr, &n); /* Discard oldest n events. */ memmove (input_rec, input_rec + n, m::bytes (total_read)); con.num_processed -= n; nowait = true; } release_attach_mutex (); break; case WAIT_TIMEOUT: con.num_processed = 0; case WAIT_SIGNALED: case WAIT_CANCELED: break; default: /* Error */ ReleaseMutex (p->input_mutex); return; } /* If ENABLE_VIRTUAL_TERMINAL_INPUT is not set, changing window height does not generate WINDOW_BUFFER_SIZE_EVENT. Therefore, check windows size every time here. */ if (!wincap.has_con_24bit_colors () || con_is_legacy) { SHORT y = con.dwWinSize.Y; SHORT x = con.dwWinSize.X; con.fillin (p->output_handle); if (y != con.dwWinSize.Y || x != con.dwWinSize.X) { con.scroll_region.Top = 0; con.scroll_region.Bottom = -1; ttyp->kill_pgrp (SIGWINCH); } } for (i = con.num_processed; i < total_read; i++) { wchar_t wc; char c; bool processed = false; switch (input_rec[i].EventType) { case KEY_EVENT: if (!input_rec[i].Event.KeyEvent.bKeyDown) continue; wc = input_rec[i].Event.KeyEvent.uChar.UnicodeChar; if (!wc || (wint_t) wc >= 0x80) continue; c = (char) wc; switch (process_sigs (c, ttyp, NULL)) { case signalled: case not_signalled_but_done: case done_with_debugger: processed = true; ttyp->output_stopped = false; if (ti.c_lflag & NOFLSH) goto remove_record; con.num_processed = 0; goto skip_writeback; default: /* not signalled */ break; } processed = process_stop_start (c, ttyp); break; case WINDOW_BUFFER_SIZE_EVENT: SHORT y = con.dwWinSize.Y; SHORT x = con.dwWinSize.X; con.fillin (p->output_handle); if (y != con.dwWinSize.Y || x != con.dwWinSize.X) { con.scroll_region.Top = 0; con.scroll_region.Bottom = -1; if (wincap.has_con_24bit_colors () && !con_is_legacy) fix_tab_position (p->output_handle); ttyp->kill_pgrp (SIGWINCH); } processed = true; break; } remove_record: if (processed) { /* Remove corresponding record. */ if (total_read > i + 1) memmove (input_rec + i, input_rec + i + 1, m::bytes (total_read - i - 1)); total_read--; i--; } } con.num_processed = total_read; if (total_read) { do { INPUT_RECORD tmp[inrec_size]; /* Writeback input records other than interrupt. */ acquire_attach_mutex (mutex_timeout); WriteConsoleInputW (p->input_handle, input_rec, total_read, &n); /* Check if writeback was successfull. */ PeekConsoleInputW (p->input_handle, tmp, inrec_size, &n); release_attach_mutex (); 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)) == 0) break; /* OK */ /* Try to fix */ DWORD incr = n - total_read; DWORD ofst; for (ofst = 1; ofst <= incr; ofst++) if (memcmp (input_rec, tmp + ofst, m::bytes (total_read)) == 0) { 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 = n; break; } if (ofst > incr) break; /* Writeback was not atomic. Or someone has read input without acquiring input_mutex. Giving up because hard to fix. */ } while (true); } skip_writeback: ReleaseMutex (p->input_mutex); if (!nowait) cygwait (40); } }
-- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple