From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7868) id 3C20F3857B9E; Sat, 2 Jul 2022 02:24:40 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3C20F3857B9E 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: Allow pasting very long text input. X-Act-Checkin: newlib-cygwin X-Git-Author: Takashi Yano X-Git-Refname: refs/heads/cygwin-3_3-branch X-Git-Oldrev: 5603daa90003aba39454b0e9b53d3ab79a9e041d X-Git-Newrev: 15dd408118293230610f3434231a3c9d655a4efe Message-Id: <20220702022440.3C20F3857B9E@sourceware.org> Date: Sat, 2 Jul 2022 02:24:40 +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: Sat, 02 Jul 2022 02:24:40 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D15dd4081182= 93230610f3434231a3c9d655a4efe commit 15dd408118293230610f3434231a3c9d655a4efe Author: Takashi Yano Date: Fri Jul 1 12:08:41 2022 +0900 Cygwin: console: Allow pasting very long text input. =20 - 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 Diff: --- winsup/cygwin/fhandler.h | 1 + winsup/cygwin/fhandler_console.cc | 121 +++++++++++++++++++++++++++++-----= ---- winsup/cygwin/release/3.3.6 | 4 ++ winsup/cygwin/wincap.cc | 11 ++++ winsup/cygwin/wincap.h | 2 + 5 files changed, 112 insertions(+), 27 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 9940da771..2b403d06e 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(). */ =20 diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_con= sole.cc index f41a8213a..c95716c5f 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 =3D 128; /* Possible max number of incoming e= vents during the process. Additional space should be left for writeback fix. */ - const int inrec_size =3D INREC_SIZE + additional_space; + DWORD inrec_size =3D INREC_SIZE + additional_space; + INPUT_RECORD *input_rec =3D + (INPUT_RECORD *) malloc (inrec_size * sizeof (INPUT_RECORD)); + INPUT_RECORD *input_tmp =3D + (INPUT_RECORD *) malloc (inrec_size * sizeof (INPUT_RECORD)); + + if (!input_rec || !input_tmp) + return; /* Cannot continue */ + + DWORD inrec_size1 =3D + 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 =3D=3D myself->pid) { DWORD total_read, n, i; - INPUT_RECORD input_rec[inrec_size]; =20 if (con.disable_master_thread) { @@ -309,25 +319,55 @@ fhandler_console::cons_master_thread (handle_set_t *p= , tty *ttyp) continue; } =20 + 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 =3D true; + continue; + } + total_read =3D n; + } + con.master_thread_suspended =3D false; + if (total_read + additional_space > inrec_size) + { + DWORD new_inrec_size =3D total_read + additional_space; + INPUT_RECORD *new_input_rec =3D (INPUT_RECORD *) + realloc (input_rec, new_inrec_size * sizeof (INPUT_RECORD)); + INPUT_RECORD *new_input_tmp =3D (INPUT_RECORD *) + realloc (input_tmp, new_inrec_size * sizeof (INPUT_RECORD)); + if (new_input_rec && new_input_tmp) + { + inrec_size =3D new_inrec_size; + input_rec =3D new_input_rec; + input_tmp =3D new_input_tmp; + if (!wincap.cons_need_small_input_record_buf ()) + inrec_size1 =3D inrec_size; + } + } + WaitForSingleObject (p->input_mutex, mutex_timeout); total_read =3D 0; - bool nowait =3D 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 =3D=3D INREC_SIZE /* Working space full */ - && cygwait (p->input_handle, (DWORD) 0) =3D=3D WAIT_OBJECT_0) + total_read =3D 0; + while (cygwait (p->input_handle, (DWORD) 0) =3D=3D WAIT_OBJECT_0) { - const int incr =3D 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 -=3D n; - nowait =3D true; + DWORD len; + ReadConsoleInputW (p->input_handle, input_rec + total_read, + min (inrec_size - total_read, inrec_size1), + &len); + total_read +=3D 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 =3D 0; + while (n < total_read) + { + DWORD len; + WriteConsoleInputW (p->input_handle, input_rec + n, + min (total_read - n, inrec_size1), &len); + n +=3D 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 =3D 0; + while (cygwait (p->input_handle, (DWORD) 0) =3D=3D WAIT_OBJECT_0) + { + DWORD len; + ReadConsoleInputW (p->input_handle, input_tmp + n, + min (inrec_size - n, inrec_size1), &len); + n +=3D len; + } 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)) + if (i =3D=3D total_read + || !inrec_eq (input_rec + i, input_tmp + j, 1)) { if (total_read + j - i >=3D 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 =3D 0; + while (n < total_read) + { + DWORD len; + WriteConsoleInputW (p->input_handle, input_rec + n, + min (total_read - n, inrec_size1), &len); + n +=3D len; + } release_attach_mutex (); goto skip_writeback; } - input_rec[total_read + j - i] =3D tmp[j]; + input_rec[total_read + j - i] =3D 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); } =20 bool @@ -548,6 +612,7 @@ fhandler_console::setup () shared_console_info->tty_min_state.is_console =3D true; con.cursor_key_app_mode =3D false; con.disable_master_thread =3D true; + con.master_thread_suspended =3D false; con.num_processed =3D 0; } } @@ -601,6 +666,8 @@ fhandler_console::set_input_mode (tty::cons_mode m, con= st termios *t, break; case tty::cygwin: flags |=3D ENABLE_WINDOW_INPUT; + if (con.master_thread_suspended) + flags |=3D ENABLE_PROCESSED_INPUT; if (wincap.has_con_24bit_colors () && !con_is_legacy) flags |=3D 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 f1a4b7812..44a7bcf9d 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 af34de5a4..f37ed6b6a 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -52,6 +52,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll= _common"), shared)) =3D { has_tcp_maxrtms:false, has_query_process_handle_info:false, has_broken_attach_console:true, + cons_need_small_input_record_buf:true, }, }; =20 @@ -89,6 +90,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_com= mon"), shared)) =3D { has_tcp_maxrtms:false, has_query_process_handle_info:false, has_broken_attach_console:true, + cons_need_small_input_record_buf:true, }, }; =20 @@ -126,6 +128,7 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_c= ommon"), shared)) =3D { has_tcp_maxrtms:false, has_query_process_handle_info:true, has_broken_attach_console:false, + cons_need_small_input_record_buf:false, }, }; =20 @@ -163,6 +166,7 @@ wincaps wincap_8_1 __attribute__((section (".cygwin_dll= _common"), shared)) =3D { has_tcp_maxrtms:false, has_query_process_handle_info:true, has_broken_attach_console:false, + cons_need_small_input_record_buf:false, }, }; =20 @@ -200,6 +204,7 @@ wincaps wincap_10_1507 __attribute__((section (".cygwi= n_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, }, }; =20 @@ -237,6 +242,7 @@ wincaps wincap_10_1607 __attribute__((section (".cygwi= n_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, }, }; =20 @@ -274,6 +280,7 @@ wincaps wincap_10_1703 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_tcp_maxrtms:true, has_query_process_handle_info:true, has_broken_attach_console:false, + cons_need_small_input_record_buf:false, }, }; =20 @@ -311,6 +318,7 @@ wincaps wincap_10_1709 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_tcp_maxrtms:true, has_query_process_handle_info:true, has_broken_attach_console:false, + cons_need_small_input_record_buf:false, }, }; =20 @@ -348,6 +356,7 @@ wincaps wincap_10_1803 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_tcp_maxrtms:true, has_query_process_handle_info:true, has_broken_attach_console:false, + cons_need_small_input_record_buf:false, }, }; =20 @@ -385,6 +394,7 @@ wincaps wincap_10_1809 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_tcp_maxrtms:true, has_query_process_handle_info:true, has_broken_attach_console:false, + cons_need_small_input_record_buf:false, }, }; =20 @@ -422,6 +432,7 @@ wincaps wincap_10_1903 __attribute__((section (".cygwin= _dll_common"), shared)) =3D has_tcp_maxrtms:true, has_query_process_handle_info:true, has_broken_attach_console:false, + cons_need_small_input_record_buf:false, }, }; =20 diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 63911d079..c5e7c9aa6 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; }; }; =20 @@ -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) =20 void disable_case_sensitive_dirs () {