[PATCH v8 2/7] Cygwin: pty: Add workaround for handling of backspace when pcon enabled
Johannes Schindelin
Johannes.Schindelin@gmx.de
Sat Mar 28 13:34:35 GMT 2026
Hi Takashi,
On Sat, 28 Mar 2026, Takashi Yano wrote:
> On Sat, 28 Mar 2026 19:55:46 +0900 Takashi Yano wrote:
>
> > @@ -2241,28 +2246,75 @@ fhandler_pty_master::write (const void *ptr, size_t len)
> > { /* Reaches here when non-cygwin app is foreground and pseudo console
> > is activated. */
> > tmp_pathbuf tp;
> > - char *buf = (char *) ptr;
> > + char *buf = tp.c_get ();
> > size_t nlen = len;
> > if (get_ttyp ()->term_code_page != CP_UTF8)
> > {
> > static mbstate_t mbp;
> > - buf = tp.c_get ();
> > nlen = NT_MAX_PATH;
> > convert_mb_str (CP_UTF8, buf, &nlen,
> > get_ttyp ()->term_code_page, (const char *) ptr, len,
> > &mbp);
> > }
> > + else
> > + memcpy (buf, ptr, nlen);
> >
> > - for (size_t i = 0; i < nlen; i++)
> > + if (get_ttyp ()->nat_pipe_owner_pid != nat_pipe_owner_pid_dupped
> > + && !nat_pipe_owner_self (get_ttyp ()->nat_pipe_owner_pid))
> > + {
> > + if (h_pcon_in_dupped)
> > + ForceCloseHandle (h_pcon_in_dupped);
> > + h_pcon_in_dupped = NULL;
> > + nat_pipe_owner_pid_dupped = 0;
> > + HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
> > + get_ttyp ()->nat_pipe_owner_pid);
> > + if (pcon_owner)
> > + {
> > + DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
> > + GetCurrentProcess (), &h_pcon_in_dupped,
> > + 0, FALSE, DUPLICATE_SAME_ACCESS);
> > + nat_pipe_owner_pid_dupped = get_ttyp ()->nat_pipe_owner_pid;
> > + CloseHandle(pcon_owner);
> > + }
> > + }
> > + else
> > + {
> > + h_pcon_in_dupped = get_ttyp ()->h_pcon_in;
> > + nat_pipe_owner_pid_dupped = get_ttyp ()->nat_pipe_owner_pid;
> > + }
>
> Oops! This is wrong.
>
> Should be:
> + if (get_ttyp ()->nat_pipe_owner_pid != nat_pipe_owner_pid_dupped)
> + {
> + if (!nat_pipe_owner_self (get_ttyp ()->nat_pipe_owner_pid))
> + {
> + if (h_pcon_in_dupped)
> + ForceCloseHandle (h_pcon_in_dupped);
> + h_pcon_in_dupped = NULL;
> + nat_pipe_owner_pid_dupped = 0;
> + HANDLE pcon_owner = OpenProcess (PROCESS_DUP_HANDLE, FALSE,
> + get_ttyp ()->nat_pipe_owner_pid);
> + if (pcon_owner)
> + {
> + DuplicateHandle (pcon_owner, get_ttyp ()->h_pcon_in,
> + GetCurrentProcess (), &h_pcon_in_dupped,
> + 0, FALSE, DUPLICATE_SAME_ACCESS);
> + nat_pipe_owner_pid_dupped = get_ttyp ()->nat_pipe_owner_pid;
> + CloseHandle(pcon_owner);
> + }
> + }
> + else
> + {
> + h_pcon_in_dupped = get_ttyp ()->h_pcon_in;
> + nat_pipe_owner_pid_dupped = get_ttyp ()->nat_pipe_owner_pid;
> + }
> + }
Ah, that makes sense. Even the `else` clause should be guarded by the
`nat_pipe_owner_pid != nat_pipe_owner_pid_dupped` guard.
About the patch itself: I am not super-hyped about the proliferation of
handles, but honestly, I do not see any good alternative either.
Thank you!
Johannes
>
> > +
> > + /* Retrieve console mode */
> > + DWORD cons_mode = ENABLE_VIRTUAL_TERMINAL_INPUT;
> > + if (h_pcon_in_dupped && memchr (buf, '\010' /* Ctrl-H */, nlen))
> > + {
> > + if (!nat_pipe_owner_self (nat_pipe_owner_pid_dupped))
> > + {
> > + DWORD resume_pid =
> > + attach_console_temporarily (nat_pipe_owner_pid_dupped);
> > + GetConsoleMode (h_pcon_in_dupped, &cons_mode);
> > + resume_from_temporarily_attach (resume_pid);
> > + }
> > + else
> > + GetConsoleMode (h_pcon_in_dupped, &cons_mode);
> > + }
> > +
> > + len = nlen;
> > + for (size_t i = 0, j = 0; i < len; i++)
> > {
> > process_sig_state r = process_sigs (buf[i], get_ttyp (), this);
> > - if (r == done_with_debugger)
> > + if (r != done_with_debugger)
> > {
> > - for (size_t j = i; j < nlen - 1; j++)
> > - buf[j] = buf[j + 1];
> > - nlen--;
> > - i--;
> > + char c = buf[i];
> > + /* Workaround for pseudo console in Windows 11 */
> > + if (!(cons_mode & ENABLE_VIRTUAL_TERMINAL_INPUT))
> > + /* Undesired backspace conversion in pseudo console does
> > + not happen if ENABLE_VIRTUAL_TERMINAL_INPUT is set. */
> > + if (c == '\010') /* Ctrl-H */
> > + c = '\177'; /* Backspace */
> > + buf[j++] = c;
> > }
> > + else
> > + nlen--;
> > }
> >
> > DWORD n;
> > @@ -3998,6 +4050,10 @@ fhandler_pty_slave::transfer_input (tty::xfer_dir dir, HANDLE from, tty *ttyp,
> > if (r[i].EventType == KEY_EVENT && r[i].Event.KeyEvent.bKeyDown)
> > {
> > DWORD ctrl_key_state = r[i].Event.KeyEvent.dwControlKeyState;
> > + if (r[i].Event.KeyEvent.uChar.AsciiChar == '\010' /* Ctrl-H */
> > + && !(ctrl_key_state & ALT_PRESSED))
> > + /* Workaround for pseudo console in Windows 11 */
> > + r[i].Event.KeyEvent.uChar.AsciiChar = '\177'; /* Backspace */
> > if (r[i].Event.KeyEvent.uChar.AsciiChar)
> > {
> > if ((ctrl_key_state & ALT_PRESSED)
> > diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
> > index 16f55b4f7..7ea04a26c 100644
> > --- a/winsup/cygwin/local_includes/fhandler.h
> > +++ b/winsup/cygwin/local_includes/fhandler.h
> > @@ -2564,6 +2564,8 @@ private:
> > HANDLE thread_param_copied_event;
> > HANDLE helper_goodbye;
> > HANDLE helper_h_process;
> > + HANDLE h_pcon_in_dupped;
> > + DWORD nat_pipe_owner_pid_dupped;
> >
> > public:
> > HANDLE get_echo_handle () const { return echo_r; }
> > --
> > 2.51.0
> >
>
>
> --
> Takashi Yano <takashi.yano@nifty.ne.jp>
>
More information about the Cygwin-patches
mailing list