aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorTakashi Yano <takashi.yano@nifty.ne.jp>2022-07-01 12:08:41 +0900
committerTakashi Yano <takashi.yano@nifty.ne.jp>2022-07-02 11:01:21 +0900
commit15dd408118293230610f3434231a3c9d655a4efe (patch)
tree87c3dca09fd68df066ac4b0dfb428324c2d4e63d /winsup
parent5603daa90003aba39454b0e9b53d3ab79a9e041d (diff)
downloadnewlib-15dd408118293230610f3434231a3c9d655a4efe.zip
newlib-15dd408118293230610f3434231a3c9d655a4efe.tar.gz
newlib-15dd408118293230610f3434231a3c9d655a4efe.tar.bz2
Cygwin: console: Allow pasting very long text input.
- 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
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/fhandler.h1
-rw-r--r--winsup/cygwin/fhandler_console.cc121
-rw-r--r--winsup/cygwin/release/3.3.64
-rw-r--r--winsup/cygwin/wincap.cc11
-rw-r--r--winsup/cygwin/wincap.h2
5 files changed, 112 insertions, 27 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 9940da7..2b403d0 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2090,6 +2090,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 f41a821..c95716c 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
{
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);
+ total_read += len;
}
release_attach_mutex ();
break;
@@ -415,33 +455,56 @@ remove_record:
{
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);
+ n = 0;
+ while (n < total_read)
+ {
+ DWORD len;
+ WriteConsoleInputW (p->input_handle, input_rec + n,
+ min (total_read - n, inrec_size1), &len);
+ n += len;
+ }
/* Check if writeback was successfull. */
- PeekConsoleInputW (p->input_handle, tmp, inrec_size, &n);
+ PeekConsoleInputW (p->input_handle, input_tmp, inrec_size1, &n);
release_attach_mutex ();
- if (n < total_read)
+ if (n < min (total_read, inrec_size1))
break; /* Someone has read input without acquiring
input_mutex. ConEmu cygwin-connector? */
- if (inrec_eq (input_rec, tmp, total_read))
+ if (inrec_eq (input_rec, input_tmp,
+ min (total_read, inrec_size1)))
break; /* OK */
/* Try to fix */
acquire_attach_mutex (mutex_timeout);
- ReadConsoleInputW (p->input_handle, tmp, inrec_size, &n);
+ n = 0;
+ while (cygwait (p->input_handle, (DWORD) 0) == WAIT_OBJECT_0)
+ {
+ DWORD len;
+ ReadConsoleInputW (p->input_handle, input_tmp + n,
+ min (inrec_size - n, inrec_size1), &len);
+ n += len;
+ }
release_attach_mutex ();
for (DWORD i = 0, j = 0; j < n; j++)
- if (i == total_read || !inrec_eq (input_rec + i, tmp + j, 1))
+ if (i == total_read
+ || !inrec_eq (input_rec + i, input_tmp + j, 1))
{
if (total_read + j - i >= n)
{ /* Something is wrong. Giving up. */
acquire_attach_mutex (mutex_timeout);
- WriteConsoleInputW (p->input_handle, tmp, n, &n);
+ WriteConsoleInputW (p->input_handle, input_tmp, n, &n);
+ n = 0;
+ while (n < total_read)
+ {
+ DWORD len;
+ WriteConsoleInputW (p->input_handle, input_rec + n,
+ min (total_read - n, inrec_size1), &len);
+ n += len;
+ }
release_attach_mutex ();
goto skip_writeback;
}
- input_rec[total_read + j - i] = tmp[j];
+ input_rec[total_read + j - i] = input_tmp[j];
}
else
i++;
@@ -451,9 +514,10 @@ remove_record:
}
skip_writeback:
ReleaseMutex (p->input_mutex);
- if (!nowait)
- cygwait (40);
+ cygwait (40);
}
+ free (input_rec);
+ free (input_tmp);
}
bool
@@ -548,6 +612,7 @@ fhandler_console::setup ()
shared_console_info->tty_min_state.is_console = true;
con.cursor_key_app_mode = false;
con.disable_master_thread = true;
+ con.master_thread_suspended = false;
con.num_processed = 0;
}
}
@@ -601,6 +666,8 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t,
break;
case tty::cygwin:
flags |= ENABLE_WINDOW_INPUT;
+ if (con.master_thread_suspended)
+ flags |= ENABLE_PROCESSED_INPUT;
if (wincap.has_con_24bit_colors () && !con_is_legacy)
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
else
@@ -4201,5 +4268,5 @@ fhandler_console::close_handle_set (handle_set_t *p)
bool
fhandler_console::need_console_handler ()
{
- return con.disable_master_thread;
+ return con.disable_master_thread || con.master_thread_suspended;
}
diff --git a/winsup/cygwin/release/3.3.6 b/winsup/cygwin/release/3.3.6
index f1a4b78..44a7bcf 100644
--- a/winsup/cygwin/release/3.3.6
+++ b/winsup/cygwin/release/3.3.6
@@ -22,3 +22,7 @@ Bug Fixes
if events are inquired in multiple pollfd entries on the same fd
at the same time.
Addresses: https://cygwin.com/pipermail/cygwin/2022-June/251732.html
+
+- Fix a console problem that the text longer than 1024 bytes cannot
+ be pasted correctly.
+ Addresses: https://cygwin.com/pipermail/cygwin/2022-June/251764.html
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index af34de5..f37ed6b 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -52,6 +52,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
has_tcp_maxrtms:false,
has_query_process_handle_info:false,
has_broken_attach_console:true,
+ cons_need_small_input_record_buf:true,
},
};
@@ -89,6 +90,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_tcp_maxrtms:false,
has_query_process_handle_info:false,
has_broken_attach_console:true,
+ cons_need_small_input_record_buf:true,
},
};
@@ -126,6 +128,7 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_tcp_maxrtms:false,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -163,6 +166,7 @@ wincaps wincap_8_1 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_tcp_maxrtms:false,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -200,6 +204,7 @@ wincaps wincap_10_1507 __attribute__((section (".cygwin_dll_common"), shared))
has_tcp_maxrtms:false,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -237,6 +242,7 @@ wincaps wincap_10_1607 __attribute__((section (".cygwin_dll_common"), shared))
has_tcp_maxrtms:true,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -274,6 +280,7 @@ wincaps wincap_10_1703 __attribute__((section (".cygwin_dll_common"), shared)) =
has_tcp_maxrtms:true,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -311,6 +318,7 @@ wincaps wincap_10_1709 __attribute__((section (".cygwin_dll_common"), shared)) =
has_tcp_maxrtms:true,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -348,6 +356,7 @@ wincaps wincap_10_1803 __attribute__((section (".cygwin_dll_common"), shared)) =
has_tcp_maxrtms:true,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -385,6 +394,7 @@ wincaps wincap_10_1809 __attribute__((section (".cygwin_dll_common"), shared)) =
has_tcp_maxrtms:true,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
@@ -422,6 +432,7 @@ wincaps wincap_10_1903 __attribute__((section (".cygwin_dll_common"), shared)) =
has_tcp_maxrtms:true,
has_query_process_handle_info:true,
has_broken_attach_console:false,
+ cons_need_small_input_record_buf:false,
},
};
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 63911d0..c5e7c9a 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -46,6 +46,7 @@ struct wincaps
unsigned has_tcp_maxrtms : 1;
unsigned has_query_process_handle_info : 1;
unsigned has_broken_attach_console : 1;
+ unsigned cons_need_small_input_record_buf : 1;
};
};
@@ -115,6 +116,7 @@ public:
bool IMPLEMENT (has_tcp_maxrtms)
bool IMPLEMENT (has_query_process_handle_info)
bool IMPLEMENT (has_broken_attach_console)
+ bool IMPLEMENT (cons_need_small_input_record_buf)
void disable_case_sensitive_dirs ()
{