[newlib-cygwin] Cygwin: console: Fix NOFLSH behaviour a bit

Takashi Yano via Cygwin-cvs <[email protected]> Wed, 24 Jun 2026 12:45:46 +0000 (GMT)
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3D66324edf64a=
9ef0672e445c870b5a38c091f7b38

commit 66324edf64a9ef0672e445c870b5a38c091f7b38
Author: Takashi Yano <[email protected]>
Date:   Wed Jun 10 23:42:27 2026 +0900

    Cygwin: console: Fix NOFLSH behaviour a bit
   =20
    If you run "stty noflsh; cat" in "bash", and stop "cat" by Ctrl-C,
    a stray ^C is passed to "bash". The current code calls tcflush() if
    NOFLSH is not set, however, tcflush() is not called when NOFLSH is
    set. So, Ctrl-C remains in console input buffer. This should be
    discarded even in NOFLSH mode. This patch introduces a helper
    function discard_key_events() and call it to erase Ctrl-C in the
    console input buffer.
   =20
    Note that even with this patch, NOFLSH is not fully functional in
    console because the readahead buffer is unique to process, so it
    cannot be inherited to other processes. However, it should work
    intra process.
   =20
    Fixes: 118e51be1d04 ("(tty_min::kill_pgrp): Handle tty flush when signa=
l detected.")
    Signed-off-by: Takashi Yano <[email protected]>
    Reviewed-by: Mark Geisert <[email protected]>

Diff:
---
 winsup/cygwin/fhandler/console.cc       | 20 +++++++++++++++++---
 winsup/cygwin/fhandler/termios.cc       | 10 +++++++---
 winsup/cygwin/local_includes/fhandler.h |  2 ++
 winsup/cygwin/release/3.6.10            |  2 ++
 4 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/con=
sole.cc
index a5e6cd89d..9ac492980 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -1744,17 +1744,31 @@ out:
     discard_len =3D 0;
   if (discard_len)
     {
-      DWORD discarded;
       acquire_attach_mutex (mutex_timeout);
       DWORD resume_pid =3D attach_console (con.owner);
-      ReadConsoleInputW (get_handle (), input_rec, discard_len, &discarded=
);
+      discard_key_events (discard_len);
       detach_console (resume_pid, con.owner);
       release_attach_mutex ();
-      con.num_processed -=3D min (con.num_processed, discarded);
     }
   return stat;
 }
=20
+void
+fhandler_console::discard_key_events (size_t n)
+{
+  DWORD discarded =3D 0;
+  INPUT_RECORD input_rec[INREC_SIZE];
+  DWORD n1 =3D min (INREC_SIZE, n);
+  while (n)
+    {
+      ReadConsoleInputW (get_handle (), input_rec, n1, &n1);
+      n -=3D n1;
+      discarded +=3D n1;
+      n1 =3D min (INREC_SIZE, n);
+    }
+  con.num_processed -=3D min (con.num_processed, discarded);
+}
+
 bool
 dev_console::fillin (HANDLE h)
 {
diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/ter=
mios.cc
index ca5fa4b7e..605258731 100644
--- a/winsup/cygwin/fhandler/termios.cc
+++ b/winsup/cygwin/fhandler/termios.cc
@@ -666,9 +666,13 @@ fhandler_termios::sigflush ()
      be NULL while this is alive.  However, we can conceivably close a
      ctty while exiting and that will zero this. */
   if ((!have_execed || have_execed_cygwin) && tc ()
-      && (tc ()->getpgid () =3D=3D myself->pgid)
-      && !(tc ()->ti.c_lflag & NOFLSH))
-    tcflush (TCIFLUSH);
+      && (tc ()->getpgid () =3D=3D myself->pgid))
+    {
+      if (!(tc ()->ti.c_lflag & NOFLSH))
+	tcflush (TCIFLUSH);
+      else
+	discard_key_events (1);
+    }
 }
=20
 pid_t
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_=
includes/fhandler.h
index 209b5601e..98bec80c6 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -1983,6 +1983,7 @@ class fhandler_termios: public fhandler_base
   pid_t tcgetsid ();
   virtual int fstat (struct stat *buf);
   int tcflow (int);
+  virtual void discard_key_events (size_t n) {}
=20
   fhandler_termios (void *) {}
=20
@@ -2363,6 +2364,7 @@ private:
   void wpbuf_put (char c);
   void wpbuf_send ();
   int fstat (struct stat *buf);
+  void discard_key_events (size_t n);
=20
   class console_unit
   {
diff --git a/winsup/cygwin/release/3.6.10 b/winsup/cygwin/release/3.6.10
index 597cf7bdb..c583e7746 100644
--- a/winsup/cygwin/release/3.6.10
+++ b/winsup/cygwin/release/3.6.10
@@ -20,3 +20,5 @@ Fixes:
 - Fix CR/NL conversion in accept_input() for pty.
=20
 - Ensure the cons_master_thread runs only when it is really supposed to.
+
+- Fix NOFLSH behaviour in console a bit.