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

commit 26dafb54e385981ecb13991b6ab660ee86e5c82c
Author: Takashi Yano <takashi.y...@nifty.ne.jp>
Date:   Mon Jul 14 10:40:08 2025 +0900

    Cygwin: pty: TCIFLUSH also clears readahead buffer in the master
    
    Previously, TCIFLUSH flushed the pipe to_slave which transfers
    input from master to slave. However, this was not sufficiant.
    The master side holds input data before accept_input() in the
    read-ahead buffer. So, if input data before 'enter' key can be
    leaked into slave input after TCIFLUSH.
    
    With this patch, TCIFLUSH requests master to flush read-ahead
    buffer via master control pipe. To realize this, add cmd filed
    to pipe_request structure so that the flush request can be
    distinguished from existing pipe handle request.
    
    Addresses: https://cygwin.com/pipermail/cygwin/2025-July/258442.html
    Fixes: 41946df6111b (" (fhandler_tty_slave::tcflush): Implement input queue 
flushing by calling read with NULL buffer.")
    Reported-by: Christoph Reiter <reiter.christ...@gmail.com>
    Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp>
    (cherry picked from commit 2aa41b516055ea9383508342706288deb3baf1f6)

Diff:
---
 winsup/cygwin/fhandler/pty.cc           | 31 ++++++++++++++++++++++++++-----
 winsup/cygwin/local_includes/fhandler.h |  1 +
 winsup/cygwin/release/3.6.4             |  3 +++
 3 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
index 3128b92da..36fddbbe9 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -42,7 +42,14 @@ extern "C" int sscanf (const char *, const char *, ...);
   } while (0)
 
 /* pty master control pipe messages */
+enum pipe_request_cmd {
+  GET_HANDLES,
+  FLUSH_INPUT,
+  QUIT
+};
+
 struct pipe_request {
+  pipe_request_cmd cmd;
   DWORD pid;
 };
 
@@ -871,7 +878,7 @@ fhandler_pty_slave::open (int flags, mode_t)
     }
   else
     {
-      pipe_request req = { GetCurrentProcessId () };
+      pipe_request req = { GET_HANDLES, GetCurrentProcessId () };
       pipe_reply repl;
       DWORD len;
 
@@ -1139,7 +1146,7 @@ fhandler_pty_slave::reset_switch_to_nat_pipe (void)
                      __small_sprintf (pipe,
                               "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
                               &cygheap->installation_key, get_minor ());
-                     pipe_request req = { GetCurrentProcessId () };
+                     pipe_request req = { GET_HANDLES, GetCurrentProcessId () 
};
                      pipe_reply repl;
                      DWORD len;
                      if (!CallNamedPipe (pipe, &req, sizeof req,
@@ -1597,6 +1604,14 @@ fhandler_pty_slave::tcflush (int queue)
 
   if (queue == TCIFLUSH || queue == TCIOFLUSH)
     {
+      char pipe[MAX_PATH];
+      __small_sprintf (pipe,
+                      "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
+                      &cygheap->installation_key, get_minor ());
+      pipe_request req = { FLUSH_INPUT, GetCurrentProcessId () };
+      pipe_reply repl;
+      DWORD n;
+      CallNamedPipe (pipe, &req, sizeof req, &repl, sizeof repl, &n, 500);
       size_t len = UINT_MAX;
       read (NULL, len);
       ret = ((int) len) >= 0 ? 0 : -1;
@@ -2020,7 +2035,7 @@ fhandler_pty_master::close (int flag)
       if (master_ctl && get_ttyp ()->master_pid == myself->pid)
        {
          char buf[MAX_PATH];
-         pipe_request req = { (DWORD) -1 };
+         pipe_request req = { QUIT, GetCurrentProcessId () };
          pipe_reply repl;
          DWORD len;
 
@@ -2521,13 +2536,18 @@ fhandler_pty_master::pty_master_thread (const 
master_thread_param_t *p)
          termios_printf ("RevertToSelf, %E");
          goto reply;
        }
-      if (req.pid == (DWORD) -1)       /* Request to finish thread. */
+      if (req.cmd == QUIT) /* Request to finish thread. */
        {
          /* Check if the requesting process is the master process itself. */
          if (pid == GetCurrentProcessId ())
            exit = true;
          goto reply;
        }
+      if (req.cmd == FLUSH_INPUT)
+       {
+         p->master->eat_readahead (-1);
+         goto reply;
+       }
       if (NT_SUCCESS (allow))
        {
          client = OpenProcess (PROCESS_DUP_HANDLE, FALSE, pid);
@@ -3780,6 +3800,7 @@ fhandler_pty_master::get_master_thread_param 
(master_thread_param_t *p)
   p->to_slave = get_output_handle ();
   p->master_ctl = master_ctl;
   p->input_available_event = input_available_event;
+  p->master = this;
   SetEvent (thread_param_copied_event);
 }
 
@@ -3821,7 +3842,7 @@ fhandler_pty_slave::transfer_input (tty::xfer_dir dir, 
HANDLE from, tty *ttyp,
       __small_sprintf (pipe,
                       "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl",
                       &cygheap->installation_key, ttyp->get_minor ());
-      pipe_request req = { GetCurrentProcessId () };
+      pipe_request req = { GET_HANDLES, GetCurrentProcessId () };
       pipe_reply repl;
       DWORD len;
       if (!CallNamedPipe (pipe, &req, sizeof req,
diff --git a/winsup/cygwin/local_includes/fhandler.h 
b/winsup/cygwin/local_includes/fhandler.h
index 3639a92a8..94f4bc552 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -2539,6 +2539,7 @@ public:
     HANDLE to_slave;
     HANDLE master_ctl;
     HANDLE input_available_event;
+    fhandler_pty_master *master;
   };
   /* Parameter set for the static function pty_master_fwd_thread() */
   struct master_fwd_thread_param_t {
diff --git a/winsup/cygwin/release/3.6.4 b/winsup/cygwin/release/3.6.4
index 4338214a6..fbc61c811 100644
--- a/winsup/cygwin/release/3.6.4
+++ b/winsup/cygwin/release/3.6.4
@@ -28,3 +28,6 @@ Fixes:
 
 - Fix ACL operations on directories.
   Addresses: https://cygwin.com/pipermail/cygwin/2025-July/258433.html
+
+- Make TCIFLUSH also flush read-ahead data in the master.
+  Addresses: https://cygwin.com/pipermail/cygwin/2025-July/258442.html

Reply via email to