public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: console: Prevent the order of typeahead input from swapped.
@ 2022-02-26 10:53 Takashi Yano
  0 siblings, 0 replies; only message in thread
From: Takashi Yano @ 2022-02-26 10:53 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=95a60b7fddf3aeb0d5aa8f7f1714bc7d10d4ceb9

commit 95a60b7fddf3aeb0d5aa8f7f1714bc7d10d4ceb9
Author: Takashi Yano <takashi.yano@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.

Diff:
---
 winsup/cygwin/fhandler_console.cc | 53 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 51 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc
index aa0f26450..88c0f894b 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -208,6 +208,20 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
 	case WAIT_OBJECT_0:
 	  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 = 1;
+	      size_t bytes = sizeof (INPUT_RECORD) * (total_read - incr);
+	      /* Discard oldest incr events. */
+	      memmove (input_rec, input_rec + incr, bytes);
+	      total_read -= incr;
+	      processed_up_to =
+		(processed_up_to + 1 >= incr) ? processed_up_to - incr : -1;
+	      ReadConsoleInputW (p->input_handle,
+				 input_rec + total_read, incr, &n);
+	      total_read += n;
+	    }
 	  break;
 	case WAIT_TIMEOUT:
 	  processed_up_to = -1;
@@ -291,8 +305,43 @@ remove_record:
 	}
       processed_up_to = total_read - 1;
       if (total_read)
-	/* Writeback input records other than interrupt. */
-	WriteConsoleInputW (p->input_handle, input_rec, total_read, &n);
+	{
+	  /* Writeback input records other than interrupt. */
+	  WriteConsoleInputW (p->input_handle, input_rec, total_read, &n);
+	  size_t bytes = sizeof (INPUT_RECORD) * total_read;
+	  do
+	    {
+	      const int additional_size = 128; /* Possible max number of
+						  incoming events during
+						  above process. */
+	      const int new_size = INREC_SIZE + additional_size;
+	      INPUT_RECORD tmp[new_size];
+	      /* Check if writeback was successfull. */
+	      PeekConsoleInputW (p->input_handle, tmp, new_size, &n);
+	      if (memcmp (input_rec, tmp, bytes) == 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, bytes) == 0)
+		  {
+		    ReadConsoleInputW (p->input_handle, tmp, new_size, &n);
+		    DWORD m;
+		    WriteConsoleInputW (p->input_handle, tmp + ofst,
+					total_read, &m);
+		    WriteConsoleInputW (p->input_handle, tmp, ofst, &m);
+		    if ( n > ofst + total_read)
+		      WriteConsoleInputW (p->input_handle,
+					  tmp + ofst + total_read,
+					  n - (ofst + total_read), &m);
+		    break;
+		  }
+	      if (ofst > incr) /* Hard to fix */
+		break; /* Giving up */
+	    }
+	  while (true);
+	}
 skip_writeback:
       ReleaseMutex (p->input_mutex);
       cygwait (40);


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-02-26 10:53 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-26 10:53 [newlib-cygwin] Cygwin: console: Prevent the order of typeahead input from swapped Takashi Yano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).