[PATCH 0/4] Fix out-of-order keystrokes

Johannes Schindelin Johannes.Schindelin@gmx.de
Tue Mar 17 13:57:05 GMT 2026


Hi Takashi,

On Tue, 17 Mar 2026, Takashi Yano wrote:

> On Tue, 10 Mar 2026 17:56:52 +0900
> Takashi Yano wrote:
> > 
> > On Fri, 6 Mar 2026 08:46:40 +0100 (CET)
> > Johannes Schindelin wrote:
> > > 
> > > Hi Takashi,
> > > 
> > > On Tue, 3 Mar 2026, Takashi Yano wrote:
> > > 
> > > > On Mon, 02 Mar 2026 14:24:36 +0000
> > > > "Johannes Schindelin wrote:
> > > > > A Git for Windows user reported that typing in a Bash session while a native
> > > > > Windows program is running (or has just exited) can produce scrambled input
> > > > > -- e.g. typing "git log" yields "igt olg":
> > > > > https://github.com/git-for-windows/git/issues/5632
> > > > > 
> > > > > [...]
> > > > 
> > > > Is the issue reproducible in pcon_activated case?
> > > > Or disable_pcon case?
> > > > 
> > > > If you can reproduce the issue in cygwin, could you kindly please
> > > > let me know how to reproduce it?
> > > 
> > > It is admittedly difficult to reproduce. It took me a good 4 days to get
> > > to a reliable reproducer. And I failed to do this in manual mode, I had to
> > > employ the help of AutoHotKey to do it. The result can be seen here:
> > > https://github.com/dscho/msys2-runtime/blob/fix-jumbled-character-order/ui-tests/keystroke-order.ahk
> > > 
> > > Unfortunately, it is not quite stand-alone, it requires `powershell.exe`
> > > in the `PATH`, and
> > > https://github.com/dscho/msys2-runtime/blob/fix-jumbled-character-order/ui-tests/ui-test-library.ahk
> > > and
> > > https://github.com/dscho/msys2-runtime/blob/fix-jumbled-character-order/ui-tests/cpu-stress.ps1
> > > in the same directory. I just verified that it reproduces even with vanilla
> > > Cygwin, using the latest AutoHotKey version from
> > > https://github.com/AutoHotkey/AutoHotkey/releases/tag/v2.0.21. I ensured
> > > that Cygwin's `bin` directory is first in the `PATH` and then ran, from a
> > > PowerShell session:
> > > 
> > >   & "<path-to>\AutoHotkey64.exe" /force keystroke-order.ahk "$PWD\log.txt"
> > > 
> > > What this test does: It runs a small PowerShell script designed to add a
> > > bit of CPU load and then spawns a Cygwin process (`sleep 1`). While these
> > > are running, it then types _very_ rapidly four characters, then two
> > > backspaces, then repeats that quite a few times ("ABXY" then deleting
> > > "XY", then "CDXY", deleting "XY", etc). The number of characters was
> > > chosen high enough that this reproducer basically reproduces the issue on
> > > the first try. The "log.txt" file contains a detailed log including the
> > > verdict. In my latest test, for example, it shows:
> > > 
> > >   Iteration 1 of 20
> > >   MISMATCH in iteration 1!
> > >   Expected: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
> > >   Got:      ABCDEFGHIJKLMNOPQRXSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
> > > 
> > > You will spot the "X" between "R" and "S", meaning that the backspace was
> > > not able to remove the "X" because it was routed to the wrong pipe, or
> > > after the "X" was already consumed.
> > 
> > Thanks for the reproducer. I finally could reproduce the issue!
> > Please let me take a look.
> 
> I finally have a patch series that fixes all the issue triggered by
> this reproducer.

Seeing as you did not reuse any part of my patches, not even the carefully
crafted commit messages, I wonder why you find them so horrible that you
don't even review them, let alone consider using them.

> I'll submit the patch series to cygwin-patches mailing list.
> Could you please test?

Yes, I tested. There is already a problem in the `cmd.exe` test I
introduced in response to your feedback. What it does is to launch
`cmd.exe`, wait a few milliseconds, and then start typing `echo
<long-string>`.

As you can see from the output here, that does not work. The first two
characters never make it to `cmd.exe`, and besides, `cmd.exe` is then
stuck:

-- snip --
$ cmd.exe
eMicrosoft Windows [Version 10.0.26200.7984]c
(c) Microsoft Corporation. All rights reserved.

D:\git-sdk-64\usr\src\MSYS2-packages\msys2-runtime\src\wip\ui-tests\msys2>ho ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
-- snap --

In my investigations (supported by Claude Opus, because I still have a
hard time with the current shape of the code and its lack of documenting
ideas clearly), I stumbled across something that I _think_ is the actual
cause of the many problems: When a native program is started, there is
this time window during which the console owner is the current process (in
my case, Bash), _not_ the native process (because it does not exist yet or
the parent process does not yet know its process ID). When any kind of
transfer happens during that time (and it does!), we're heading straight
into trouble. I get the impression that we need to address this, to close
that time window, not by narrowing it further, but by eliminating it
entirely: while a native process is starting up that will become the
console's owner, no transfer should happen.

Now, I really would like to collaborate with you on that. But I have to
admit that I'm struggling a bit when you don't even comment on the
contents of the commit message or patch to help me improve them, or when
you just ignore those patches and instead write completely different ones.

Can we work on this together, please?

Ciao,
Johannes

For your viewing pleasure, the change for the AutoHotKey test:

-- snipsnap --
From f24131d4971f4652c15f1ab53ac0180275bd3e0f Mon Sep 17 00:00:00 2001
From: Johannes Schindelin <johannes.schindelin@gmx.de>
Date: Fri, 6 Mar 2026 13:20:49 +0100
Subject: [PATCH] squash! ui-tests: add a reproducer for the keystroke
 reordering bug

An early iteration of the "Fix out-of-order keystrokes" patch series had
a bug where it would prevent native processes from receiving _any_
keystrokes under certain circumstances. Let's also specifically verify
that this is _not_ the case, and prevent regressing on it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 ui-tests/keystroke-order.ahk | 69 ++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/ui-tests/keystroke-order.ahk b/ui-tests/keystroke-order.ahk
index e6161a782c..81ee651b11 100644
--- a/ui-tests/keystroke-order.ahk
+++ b/ui-tests/keystroke-order.ahk
@@ -39,6 +39,75 @@ if !InStr(capture, '$ ')
     ExitWithError 'Timed out waiting for bash prompt'
 Info 'Bash prompt appeared'
 
+; === cmd.exe input verification ===
+; Verify that input typed into cmd.exe (a native Win32 console app) is not
+; silently lost. This catches the regression where removing the pcon_start
+; post-loop block also removed the pty_input_state = to_nat transition,
+; causing keystrokes to go to the wrong pipe.
+Info '=== cmd.exe input verification ==='
+WinActivate(winId)
+SetKeyDelay 20, 20
+SendEvent('{Text}cmd.exe')
+SendEvent('{Enter}')
+; Type immediately without waiting for cmd.exe to fully start.
+Sleep 200
+SendEvent('{Text}echo ' testString)
+SendEvent('{Enter}')
+
+; Wait for the test string to appear in cmd.exe output.
+deadline := A_TickCount + 10000
+cmdOk := false
+while A_TickCount < deadline
+{
+    text := CaptureBufferFromMintty(winId)
+    ; Look for the echoed string (cmd.exe prints the command AND its output)
+    ; Count occurrences: the echo command line itself plus the output = at least 2
+    count := 0
+    searchPos := 1
+    while searchPos := InStr(text, testString, , searchPos)
+    {
+        count++
+        searchPos += StrLen(testString)
+    }
+    if count >= 2
+    {
+        Info 'cmd.exe echoed the test string correctly'
+        cmdOk := true
+        break
+    }
+    Sleep 500
+}
+if !cmdOk
+{
+    Info 'Captured text:'
+    Info text
+    ExitWithError 'cmd.exe did not echo the test string (input lost?)'
+}
+
+; Exit cmd.exe and verify we return to bash.
+WinActivate(winId)
+SetKeyDelay 20, 20
+SendEvent('{Text}exit')
+SendEvent('{Enter}')
+Sleep 1000
+
+text := CaptureBufferFromMintty(winId)
+; After exiting cmd.exe we should see a bash prompt again.
+; Find the last "$ " -- it should come after the cmd.exe session.
+lastPrompt := 0
+pos := 1
+while pos := InStr(text, '$ ', , pos)
+{
+    lastPrompt := pos
+    pos += 2
+}
+after := (lastPrompt > 0) ? Trim(SubStr(text, lastPrompt + 2)) : ''
+if after != ''
+{
+    Info 'WARNING: unexpected text after prompt: ' after
+}
+Info 'Back at bash prompt after cmd.exe'
+
 stressCmd := 'powershell.exe -File ' StrReplace(A_ScriptDir, '\', '/') '/cpu-stress.ps1'
 Info 'Foreground command: ' stressCmd
 
-- 



More information about the Cygwin-patches mailing list