- Currently, if the text longer than 1024 byte is pasted in console,
some of the text is discarded. This patch fixes the issue.
Addresses: https://cygwin.com/pipermail/cygwin/2022-June/251764.html
---
winsup/cygwin/fhandler.h | 1 +
winsup/cygwin/fhandler_console.cc | 121 +++---
winsup/cygwin/release/3.3.6 | 4 +
winsup/cygwin/wincap.cc | 12 +++
winsup/cygwin/wincap.h| 2 +
5 files changed, 113 insertions(+), 27 deletions(-)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index d7c358e7f..d5ec56a6d 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2091,6 +2091,7 @@ class dev_console
char *cons_rapoi;
bool cursor_key_app_mode;
bool disable_master_thread;
+ bool master_thread_suspended;
int num_processed; /* Number of input events in the current input buffer
already processed by cons_master_thread(). */
diff --git a/winsup/cygwin/fhandler_console.cc
b/winsup/cygwin/fhandler_console.cc
index 345117888..4f462e3e8 100644
--- a/winsup/cygwin/fhandler_console.cc
+++ b/winsup/cygwin/fhandler_console.cc
@@ -289,7 +289,18 @@ 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;
+ DWORD inrec_size = INREC_SIZE + additional_space;
+ INPUT_RECORD *input_rec =
+(INPUT_RECORD *) malloc (inrec_size * sizeof (INPUT_RECORD));
+ INPUT_RECORD *input_tmp =
+(INPUT_RECORD *) malloc (inrec_size * sizeof (INPUT_RECORD));
+
+ if (!input_rec || !input_tmp)
+return; /* Cannot continue */
+
+ DWORD inrec_size1 =
+wincap.cons_need_small_input_record_buf () ? INREC_SIZE : inrec_size;
+
struct m
{
inline static size_t bytes (size_t n)
@@ -301,7 +312,6 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty
*ttyp)
while (con.owner == myself->pid)
{
DWORD total_read, n, i;
- INPUT_RECORD input_rec[inrec_size];
if (con.disable_master_thread)
{
@@ -309,25 +319,55 @@ fhandler_console::cons_master_thread (handle_set_t *p,
tty *ttyp)
continue;
}
+ acquire_attach_mutex (mutex_timeout);
+ GetNumberOfConsoleInputEvents (p->input_handle, &total_read);
+ release_attach_mutex ();
+ if (total_read > INREC_SIZE)
+ {
+ cygwait (40);
+ acquire_attach_mutex (mutex_timeout);
+ GetNumberOfConsoleInputEvents (p->input_handle, &n);
+ release_attach_mutex ();
+ if (n < total_read)
+ {
+ /* read() seems to be called. Process special keys
+in process_input_message (). */
+ con.master_thread_suspended = true;
+ continue;
+ }
+ total_read = n;
+ }
+ con.master_thread_suspended = false;
+ if (total_read + additional_space > inrec_size)
+ {
+ DWORD new_inrec_size = total_read + additional_space;
+ INPUT_RECORD *new_input_rec = (INPUT_RECORD *)
+ realloc (input_rec, new_inrec_size * sizeof (INPUT_RECORD));
+ INPUT_RECORD *new_input_tmp = (INPUT_RECORD *)
+ realloc (input_tmp, new_inrec_size * sizeof (INPUT_RECORD));
+ if (new_input_rec && new_input_tmp)
+ {
+ inrec_size = new_inrec_size;
+ input_rec = new_input_rec;
+ input_tmp = new_input_tmp;
+ if (!wincap.cons_need_small_input_record_buf ())
+ inrec_size1 = inrec_size;
+ }
+ }
+
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)
+ total_read = 0;
+ while (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;
+ DWORD len;
+ ReadConsoleInputW (p->input_handle, input_rec + total_read,
+min (inrec_size - total_read, inrec_size1),
+&len);
+