[newlib-cygwin] Cygwin: console: Use input_mutex in the parent PTY in master thread

Takashi Yano tyan0@sourceware.org
Sun Mar 29 00:43:55 GMT 2026


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

commit c4fb720afcf120a028f776dde47cacd2d91f3a14
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date:   Tue Mar 17 11:04:52 2026 +0900

    Cygwin: console: Use input_mutex in the parent PTY in master thread
    
    If the console is originating from pseudo console, the input into
    console is coming from PTY master. This is because:
    
    When the pseudo console is active, and a cygwin process is started
    from non-cygwin process, `cons_master_thread()` runs inside the
    Cygwin process that inherited the pseudo console from its parent
    PTY. It reads all `INPUT_RECORD`s from the console input buffer via
    `ReadConsoleInputW()`, processes signal-generating events (e.g. Ctrl+C),
    and writes the remaining records back via `WriteConsoleInputW()`.
    Meanwhile, the PTY master process (e.g. mintty) calls
    `fhandler_pty_master::write()`, which writes keystrokes to `to_slave_nat`
    (one end of the nat pipe). Conhost reads from the other end of that
    pipe, parses the byte stream through its VT input path, and inserts
    the resulting `INPUT_RECORD`s into the console input buffer.
    
    If `cons_master_thread()` reads the buffer and removes a signal record
    while conhost is simultaneously inserting new records from the PTY
    master's write, the verify step (`inrec_eq()`) finds records in the
    buffer that were not part of the original read, reports a mismatch, and
    enters the fixup path. That fixup path itself can disturb the record
    order, turning what was merely an interference into an actual problem.
    Acquiring the PTY's `input_mutex` in `cons_master_thread()` prevents
    `fhandler_pty_master::write()` from feeding new bytes into the pipe
    while the read-process-writeback-verify cycle is in progress.
    
    Use parent input_mutex as well as input_mutex in console device in
    cons_master_thread().
    
    Fixes: 04f386e9af99 ("Cygwin: console: Inherit pcon hand over from parent pty")
    Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
    Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

Diff:
---
 winsup/cygwin/fhandler/console.cc | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
index 2a52ba575..39c4f6ff0 100644
--- a/winsup/cygwin/fhandler/console.cc
+++ b/winsup/cygwin/fhandler/console.cc
@@ -63,6 +63,7 @@ fhandler_console::console_state NO_COPY
 static bool NO_COPY inside_pcon_checked = false;
 static bool NO_COPY inside_pcon = false;
 static int NO_COPY parent_pty;
+static HANDLE NO_COPY parent_pty_input_mutex = NULL;
 
 bool NO_COPY fhandler_console::invisible_console;
 
@@ -465,6 +466,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
 	  continue;
 	}
       total_read = 0;
+      if (inside_pcon && parent_pty_input_mutex)
+	WaitForSingleObject (parent_pty_input_mutex, mutex_timeout);
       switch (cygwait (p->input_handle, (DWORD) 0))
 	{
 	case WAIT_OBJECT_0:
@@ -489,6 +492,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
 	default: /* Error */
 	  free (input_rec);
 	  free (input_tmp);
+	  if (inside_pcon && parent_pty_input_mutex)
+	    ReleaseMutex (parent_pty_input_mutex);
 	  ReleaseMutex (p->input_mutex);
 	  return;
 	}
@@ -666,6 +671,8 @@ remove_record:
 	  while (true);
 	}
 skip_writeback:
+      if (inside_pcon && parent_pty_input_mutex)
+	ReleaseMutex (parent_pty_input_mutex);
       ReleaseMutex (p->input_mutex);
       cygwait (40);
     }
@@ -1971,6 +1978,8 @@ fhandler_console::setup_pcon_hand_over ()
 	    inside_pcon = true;
 	    atexit (fhandler_console::pcon_hand_over_proc);
 	    parent_pty = i;
+	    parent_pty_input_mutex =
+	      cygwin_shared->tty[i]->open_input_mutex (MAXIMUM_ALLOWED);
 	    break;
 	  }
       }
@@ -1997,6 +2006,7 @@ fhandler_console::pcon_hand_over_proc (void)
   else
     system_printf("Acquiring pcon_ho_mutex failed.");
   ReleaseMutex (mtx);
+  ForceCloseHandle (parent_pty_input_mutex);
 }
 
 bool


More information about the Cygwin-cvs mailing list