[PATCH] Cygwin: console: Allow pasting very long text input.

2022-07-01 Thread Takashi Yano
- 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, _read);
+  release_attach_mutex ();
+  if (total_read > INREC_SIZE)
+   {
+ cygwait (40);
+ acquire_attach_mutex (mutex_timeout);
+ GetNumberOfConsoleInputEvents (p->input_handle, );
+ 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, _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, );
- /* 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),
+);
+ total_read += 

Re: [PATCH] Cygwin: spawn: Treat empty path as the current directory.

2022-07-01 Thread Ken Brown

On 7/1/2022 7:31 PM, Takashi Yano wrote:

On Thu, 30 Jun 2022 21:16:35 -0400
Ken Brown wrote:

On 6/30/2022 11:45 AM, Ken Brown wrote:

On 6/27/2022 8:44 AM, Takashi Yano wrote:

- With this patch, the empty path (empty element in PATH or PATH is
    absent) is treated as the current directory as Linux does.
Addresses: https://cygwin.com/pipermail/cygwin/2022-June/251730.html


It might be a good idea to include a comment in the code and the commit message
that this feature is being added for Linux compatibility but that it is
deprecated.  According to https://man7.org/linux/man-pages/man7/environ.7.html,

    As a legacy feature, a zero-length prefix (specified as
    two adjacent colons, or an initial or terminating colon)
    is interpreted to mean the current working directory.
    However, use of this feature is deprecated, and POSIX
    notes that a conforming application shall use an explicit
    pathname (e.g., .)  to specify the current working
    directory.

Alternatively, maybe this is a case where we should prefer POSIX compliance to
Linux compatibility.  Corinna, WDYT?


I withdraw my suggestion.  There's already a comment in the code saying, "An
empty path or '.' means the current directory", so it's clear that the intention
was to support that feature, and the code was simply buggy.

I've now read through the patch, and it looks good to me.  This was pretty
tricky to get right.


We still need to discuss whether it is better to align Linux
behavior or just keeping POSIX compliance, don't we?


I interpreted the existing comment as meaning that a decision was already made 
at some point to align with Linux.  But it can't hurt to wait for Corinna to 
weigh in.


Ken


Re: [PATCH] Cygwin: spawn: Treat empty path as the current directory.

2022-07-01 Thread Takashi Yano
On Thu, 30 Jun 2022 21:16:35 -0400
Ken Brown wrote:
> On 6/30/2022 11:45 AM, Ken Brown wrote:
> > On 6/27/2022 8:44 AM, Takashi Yano wrote:
> >> - With this patch, the empty path (empty element in PATH or PATH is
> >>    absent) is treated as the current directory as Linux does.
> >> Addresses: https://cygwin.com/pipermail/cygwin/2022-June/251730.html
> > 
> > It might be a good idea to include a comment in the code and the commit 
> > message 
> > that this feature is being added for Linux compatibility but that it is 
> > deprecated.  According to 
> > https://man7.org/linux/man-pages/man7/environ.7.html,
> > 
> >    As a legacy feature, a zero-length prefix (specified as
> >    two adjacent colons, or an initial or terminating colon)
> >    is interpreted to mean the current working directory.
> >    However, use of this feature is deprecated, and POSIX
> >    notes that a conforming application shall use an explicit
> >    pathname (e.g., .)  to specify the current working
> >    directory.
> > 
> > Alternatively, maybe this is a case where we should prefer POSIX compliance 
> > to 
> > Linux compatibility.  Corinna, WDYT?
> 
> I withdraw my suggestion.  There's already a comment in the code saying, "An 
> empty path or '.' means the current directory", so it's clear that the 
> intention 
> was to support that feature, and the code was simply buggy.
> 
> I've now read through the patch, and it looks good to me.  This was pretty 
> tricky to get right.

We still need to discuss whether it is better to align Linux
behavior or just keeping POSIX compliance, don't we?

-- 
Takashi Yano