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

commit dfd1ca3a6ec28c925711f2a06298eafa717488e1
Author: Takashi Yano <[email protected]>
Date:   Tue Mar 10 11:22:08 2026 +0900

    Cygwin: signal: Implement fake stop/cont for non-cygwin process
    
    Currently, the following command in bash cannot make `cat | cmd`
    foreground correctly, and also cannot be terminated by Ctrl-C.
    
      $ cat |cmd &
      $ fg
      $ (Ctrl-C)
    
    This is because, bash does not recognize the process `cmd` as stopped
    by SIGTTIN, and does not send SIGCONT not only to `cmd` but also to
    `cat`.
    
    To solve this problem, this patch implements fake stop/cont for non-
    cygwin process such as `cmd`. Even with this patch, the process `cmd`
    does not enter into stopped state because non-cygwin process itself
    does not handle cygwin signal, but the stub process for `cmd` enters
    into stopped state instead by SIGTTIN.
    
    Signed-off-by: Takashi Yano <[email protected]>
    Reviewed-by: Corinna Vinschen <[email protected]>
    (cherry picked from commit f02f97a626aa69433651de7ce7a65f3efc010a77)

Diff:
---
 winsup/cygwin/exceptions.cc | 19 ++++++++++++++++++-
 winsup/cygwin/spawn.cc      |  2 +-
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index f79978f73..b49adc345 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -1499,6 +1499,23 @@ _cygtls::handle_SIGCONT ()
   InterlockedAnd ((LONG *) &myself->process_state, ~PID_STOPPED);
 }
 
+inline static bool
+is_stop_or_cont (int sig)
+{
+  switch (sig)
+    {
+    case SIGSTOP:
+    case SIGTSTP:
+    case SIGTTIN:
+    case SIGTTOU:
+    case SIGCONT:
+      return true;
+    default:
+      break;
+    }
+  return false;
+}
+
 int
 sigpacket::process ()
 {
@@ -1652,7 +1669,7 @@ exit_sig:
   thissig.sa_flags &= ~SA_ONSTACK;
 
 dosig:
-  if (have_execed)
+  if (have_execed && (ch_spawn.iscygwin () || !is_stop_or_cont (si.si_signo)))
     {
       sigproc_printf ("terminating captive process");
       if (::cygheap->ctty)
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 04e4a4028..81b99e763 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -877,7 +877,7 @@ child_info_spawn::worker (const char *prog_arg, const char 
*const *argv,
          if (term_spawn_worker.need_cleanup ())
            {
              LONG prev_sigExeced = sigExeced;
-             while (WaitForSingleObject (pi.hProcess, 100) == WAIT_TIMEOUT)
+             while (cygwait (pi.hProcess, 100) != WAIT_OBJECT_0)
                /* If child process does not exit in predetermined time
                   period, the process does not seem to be terminated by
                   the signal sigExeced. Therefore, clear sigExeced here. */

Reply via email to