Re: [PATCH 1/3] Cygwin: console: Ensure the master thread runs only when it is supposed to
Takashi Yano <[email protected]> Tue, 30 Jun 2026 20:51:33 +0900
| Newsgroups | gmane.os.cygwin.patches |
|---|---|
| Message-ID | <[email protected]> |
Hi Johannes,
On Mon, 29 Jun 2026 20:23:55 +0900
Takashi Yano wrote:
> Hi Johannes,
>
> On Sat, 27 Jun 2026 10:34:20 +0200 (CEST)
> Johannes Schindelin wrote:
> > Hi Takashi & Mark,
> >
> > An AutoHotKey-based test I added to
> > https://github.com/git-for-windows/msys2-runtime/pull/131 bisected a
> > Ctrl-C regression to this commit after it landed on master: Ctrl-C stopped
> > interrupting `cat` in the pipeline `cat | ping`. The diagnosis and the fix
> > I would propose are below.
> >
> > On Thu, 11 Jun 2026, Takashi Yano wrote:
> >
> > > @@ -1190,8 +1191,8 @@ fhandler_console::bg_check (int sig, bool dontsignal)
> > > in the same process group. */
> > > if (sig == SIGTTIN && con.curr_input_mode != tty::cygwin)
> > > {
> > > - set_disable_master_thread (false, this);
> > > set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
> > > + set_disable_master_thread (false, this);
> > > }
> > > if (sig == SIGTTOU && con.curr_output_mode != tty::cygwin)
> > > set_output_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
> > > @@ -2087,8 +2088,8 @@ fhandler_console::post_open_setup (int fd)
> > > /* Setting-up console mode for cygwin app started from non-cygwin app. */
> > > if (fd == 0)
> > > {
> > > - set_disable_master_thread (false, this);
> > > set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
> > > + set_disable_master_thread (false, this);
> > > }
> > > else if (fd == 1 || fd == 2)
> > > set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
> >
> > The console only delivers Ctrl-C as a raw `0x03` byte (which the console
> > master thread then reads and turns into a `SIGINT` for the foreground
> > process group) while that thread is live. When the master thread is
> > suspended or disabled, `set_input_mode (tty::cygwin)` instead requests
> > `ENABLE_PROCESSED_INPUT`, so the console raises a `CTRL_C_EVENT` and the
> > `0x03` byte never reaches the master thread.
> >
> > The reorder above has `set_input_mode (tty::cygwin)` run while
> > `disable_master_thread` is still set, so `ENABLE_PROCESSED_INPUT` stays on
> > and a cygwin program sharing a foreground pgrp with a non-cygwin program
> > (e.g. the pipeline `cat | ping`) never receives its `SIGINT`. Clearing
> > `disable_master_thread` first, so the mode is configured with the master
> > thread already live, restores the previous behavior in both `bg_check ()`
> > and `post_open_setup ()`. The disable paths and the synchronous suspension
> > this commit added are load-bearing for non-cygwin programs and are left
> > untouched, so the master thread is still reliably suspended for them.
> >
> > The fix I would propose is in
> > https://github.com/git-for-windows/msys2-runtime/pull/131/commits/73aae37a62d8246e1abaac6e52d6c6bb89bc4c5d:
>
> Thanks for catching this!
>
> > -- snip --
> > From 73aae37a62d8246e1abaac6e52d6c6bb89bc4c5d Mon Sep 17 00:00:00 2001
> > From: Johannes Schindelin <[email protected]>
> > Date: Fri, 26 Jun 2026 09:16:49 +0200
> > Subject: [PATCH] Cygwin: console: re-enable the master thread before selecting
> > cygwin input mode
> >
> > When a cygwin program and a non-cygwin program run in the same foreground
> > process group (for example the pipeline `cat | ping`), Ctrl-C stopped
> > interrupting the cygwin program after "Cygwin: console: Ensure the master
> > thread runs only when it is supposed to".
> >
> > The console only delivers Ctrl-C as a raw 0x03 byte (which the console
> > master thread reads and turns into a SIGINT for the foreground process
> > group) while that thread is live. When it is suspended or disabled,
> > set_input_mode (tty::cygwin) instead requests ENABLE_PROCESSED_INPUT, so
> > the console raises a CTRL_C_EVENT and the 0x03 byte never reaches the
> > master thread. The referenced commit reordered the two enable paths,
> > bg_check () and post_open_setup (), so that set_input_mode (tty::cygwin)
> > runs while disable_master_thread is still set; that leaves
> > ENABLE_PROCESSED_INPUT on and the cygwin program never receives its SIGINT.
> >
> > Clear disable_master_thread before selecting cygwin input mode in those two
> > paths, so the mode is configured with the master thread already live and
> > ENABLE_PROCESSED_INPUT stays off. The disable paths and the synchronous
> > suspension that the referenced commit added are left unchanged, so
> > non-cygwin programs still get the master thread reliably suspended.
> >
> > Fixes: 733d5a953fa9 ("Cygwin: console: Ensure the master thread runs only when it is supposed to")
> > Assisted-by: Opus 4.8
> > Signed-off-by: Johannes Schindelin <[email protected]>
> > ---
> > winsup/cygwin/fhandler/console.cc | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
> > index 0136652878..685e99d62c 100644
> > --- a/winsup/cygwin/fhandler/console.cc
> > +++ b/winsup/cygwin/fhandler/console.cc
> > @@ -1147,8 +1147,8 @@ fhandler_console::bg_check (int sig, bool dontsignal)
> > in the same process group. */
> > if (sig == SIGTTIN && con.curr_input_mode != tty::cygwin)
> > {
> > - set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
> > set_disable_master_thread (false, this);
> > + set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
> > }
> > if (sig == SIGTTOU && con.curr_output_mode != tty::cygwin)
> > set_output_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
> > @@ -2035,8 +2035,8 @@ fhandler_console::post_open_setup (int fd)
> > /* Setting-up console mode for cygwin app started from non-cygwin app. */
> > if (fd == 0)
> > {
> > - set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
> > set_disable_master_thread (false, this);
> > + set_input_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
> > }
> > else if (fd == 1 || fd == 2)
> > set_output_mode (tty::cygwin, &get_ttyp ()->ti, &handle_set);
> > -- snap --
>
> I think we also need the following.
>
> diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc
> index d2ffaa0c4..340bc3f2e 100644
> --- a/winsup/cygwin/fhandler/console.cc
> +++ b/winsup/cygwin/fhandler/console.cc
> @@ -991,6 +994,7 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
> termios *ti = shared_console_info[unit] ?
> &(shared_console_info[unit]->tty_min_state.ti) : &dummy;
> /* Cleaning-up console mode for non-cygwin app. */
> + set_disable_master_thread (con.owner == GetCurrentProcessId ());
> /* conmode can be tty::restore when non-cygwin app is
> exec'ed from login shell. */
> tty::cons_mode conmode = cons_mode_on_close (p);
> @@ -998,7 +1002,6 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
> set_output_mode (conmode, ti, p);
> if (con.curr_input_mode != conmode)
> set_input_mode (conmode, ti, p);
> - set_disable_master_thread (con.owner == GetCurrentProcessId ());
> }
>
> /* Return the tty structure associated with a given tty number. If the
If you agree with:
https://cygwin.com/pipermail/cygwin-patches/2026q2/015136.html
, I'll push this to master and cygwin-3_6-branch.
--
Takashi Yano <[email protected]>