Re: [PATCH] Cygwin: pty: detect pcon-backed pty for non-Cygwin-spawned children
Takashi Yano <[email protected]> Wed, 24 Jun 2026 22:12:56 +0900
| Newsgroups | gmane.os.cygwin.patches |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 30 Apr 2026 15:04:04 +0000 "Johannes Schindelin via GitGitGadget" <[email protected]> wrote: > From: Johannes Schindelin <[email protected]> > > When a Cygwin process (e.g. `bash` under MinTTY) spawns a native > Win32 child (e.g. `git.exe`) with pseudo console support enabled, > the child gets a pseudo console that bridges the pty. If that native > child then spawns a Cygwin grandchild (e.g. `vim`, `less`), the > grandchild inherits the pseudo console's console handles. In > `init_std_file_from_handle()`, the grandchild's msys2-runtime sees > `GetConsoleScreenBufferInfo()` succeed on those handles and, with > no valid `ctty` set, falls back to `FH_CONSOLE` and gives the > process `cons0` instead of connecting to the pty. > > This causes scrollback clobbering in MinTTY because alternate screen > sequences (`ESC[?1049h` / `ESC[?1049l`) are handled by > `fhandler_console`'s `save_restore()` against the pseudo > console's buffer, which has no correspondence to MinTTY's scrollback. > > Fix this in the existing console branch of > `init_std_file_from_handle()`: when there is no valid `ctty` and > we are about to fall back to `FH_CONSOLE`, first scan the shared > tty table for an entry whose `pcon_activated` is set and whose > `nat_pipe_owner_pid` is in our console's process list (via > `GetConsoleProcessList`). If found, parse the device as that pty > slave instead of as a real console. The handle is closed in either > fallback path, matching the existing `FH_CONSOLE` behavior. > `myself->ctty` is left untouched; the regular > `fhandler_pty_slave::open_setup()` path will set it via > `myself->set_ctty()` when the pty slave is opened. > > The structure of `find_pcon_pty()` matters and is easy to get > wrong in case a keen developer would like to refactor this code in > the future. This code runs on every Cygwin process startup whose > parent is non-Cygwin, so the common path (no pty with an active > pseudo console) must remain free of expensive operations. Two > pitfalls to avoid: filtering tty entries with `tty::exists()` > looks correct but creates and destroys a named pipe per entry > (128 entries on every call), and hoisting the > `GetConsoleProcessList()` call out of the loop pays the > cross-process cost even when no candidate exists. The current > shape, a cheap shared-memory boolean check first and a lazily > fetched process list only on the first candidate, keeps the > common case at a handful of pointer reads. > > Reported downstream at https://github.com/git-for-windows/git/issues/5303 > and bisected to a Git for Windows release that upgraded the bundled > msys2-runtime from 3.3.6 (no pseudo console code) to 3.4.6 (the new > pseudo console architecture). > > Fixes: bb4285206207 ("Cygwin: pty: Implement new pseudo console support.") > Assisted-by: Claude Opus 4.7 (1M context) > Signed-off-by: Johannes Schindelin <[email protected]> > --- > Detect pcon-backed pty for non-Cygwin-spawned children > > A Git for Windows user reported that vim (or less, when paging git > output) clobbers the visible scrollback in MinTTY when invoked through > git.exe: https://github.com/git-for-windows/git/issues/5303 > > Their bisect, with great patience across 60+ Git for Windows installer > reinstalls, narrowed the regression to the v2.40.1 -> v2.41.0 > transition, which corresponds to the msys2-runtime upgrade from 3.3.6 to > 3.4.6, i.e. the introduction of Takashi's pseudo console architecture > (bb4285206207). The user's diagnostic ps -f from inside vim showed the > editor on cons0 rather than pty0. > > I confirmed the root cause locally: with CYGWIN=disable_pcon the editor > lands on pty0 and the scrollback survives, with the default (pcon > enabled) it lands on cons0 and the alternate screen save/restore happens > against the pseudo console buffer, which has no relationship to MinTTY's > scrollback. The issue is reproducible without vim using a tiny > diagnostic GIT_EDITOR: > > GIT_EDITOR='sh -c "ps -f >&2; cat \"\\"" _' \ > git commit --allow-empty --amend --allow-empty > > > The sh and ps show up on cons0; with disable_pcon, on pty0. The same > symptom occurs whenever any native console application spawns Cygwin > children, git.exe is just by far the most common case in practice. > > The patch teaches init_std_file_from_handle() that an inherited console > handle from a non-Cygwin parent might actually be a pseudo console > bridging a pty, and to connect to the pty slave in that case rather than > falling back to cons0. The mechanism, the alternative I considered, and > the performance considerations for the new shared-memory scan are all in > the commit message. > > The same patch is also applied downstream at > https://github.com/git-for-windows/msys2-runtime/pull/131 so Git for > Windows users can get the fix ahead of the next Cygwin release, but this > PR is the authoritative version intended for cygwin-3_6-branch. > > Published-As: https://github.com/cygwingitgadget/cygwin/releases/tag/pr-7%2Fdscho%2Fpcon-fix-cygwin-v1 > Fetch-It-Via: git fetch https://github.com/cygwingitgadget/cygwin pr-7/dscho/pcon-fix-cygwin-v1 > Pull-Request: https://github.com/cygwingitgadget/cygwin/pull/7 > > winsup/cygwin/dtable.cc | 12 +++++++++- > winsup/cygwin/local_includes/tty.h | 5 ++++ > winsup/cygwin/tty.cc | 37 ++++++++++++++++++++++++++++++ > 3 files changed, 53 insertions(+), 1 deletion(-) [...] Pushed to master branch with my fixup patches. -- Takashi Yano <[email protected]>