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

commit a22a0ad7c4f0350a6b144be7718611630c33c503
Author: Takashi Yano <[email protected]>
Date:   Mon Dec 23 03:23:37 2024 +0900

    Cygwin: signal: Do not handle signal when __SIGFLUSHFAST is sent
    
    After the commit d243e51ef1d3, zsh sometimes hangs at startup. This
    occurs because SIGCHLD, which should trigger sigsuspend(), is handled
    in cygwait() that is used to wait for a wakeup event in sig_send(),
    even when __SIGFLUSHFAST is sent. Despite __SIGFLUSHFAST being
    required to return before handling the signal, this does not happen.
    With this patch, if the signal currently being sent is __SIGFLUSHFAST,
    do not handle the received signal and keep it asserted after the
    cygwait() for the wakeup event.  Apply the same logic to the cygwait()
    in the retrying loop for WriteFile() as well.
    
    Addresses: https://cygwin.com/pipermail/cygwin/2024-December/256954.html
    Fixes: d243e51ef1d3 ("Cygwin: signal: Fix deadlock between main thread and 
sig thread")
    Reported-by: Daisuke Fujimura <[email protected]>
    Reviewed-by: Corinna Vinschen <[email protected]>
    Signed-off-by: Takashi Yano <[email protected]>

Diff:
---
 winsup/cygwin/release/3.5.6 |  3 +++
 winsup/cygwin/sigproc.cc    | 20 +++++++++++++++-----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/winsup/cygwin/release/3.5.6 b/winsup/cygwin/release/3.5.6
index d17a6af53..0fff0de40 100644
--- a/winsup/cygwin/release/3.5.6
+++ b/winsup/cygwin/release/3.5.6
@@ -7,3 +7,6 @@ Fixes:
 
 - Fix a regression since 3.5.0 which fails to use POSIX semantics in
   unlink/rename on NTFS.
+
+- Fix zsh hang at startup.
+  Addresses: https://cygwin.com/pipermail/cygwin/2024-December/256954.html
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index ba7818a68..35ec3e70e 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -751,10 +751,14 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
       res = WriteFile (sendsig, leader, packsize, &nb, NULL);
       if (!res || packsize == nb)
        break;
-      if (cygwait (NULL, 10, cw_sig_eintr) == WAIT_SIGNALED)
+      if (cygwait (NULL, 10, cw_sig_eintr) == WAIT_SIGNALED
+         && pack.si.si_signo != __SIGFLUSHFAST)
        _my_tls.call_signal_handler ();
       res = 0;
     }
+  /* Re-assert signal_arrived which has been cleared in cygwait(). */
+  if (_my_tls.current_sig)
+    _my_tls.set_signal_arrived ();
 
   if (!res)
     {
@@ -785,7 +789,16 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
   if (wait_for_completion)
     {
       sigproc_printf ("Waiting for pack.wakeup %p", pack.wakeup);
-      rc = cygwait (pack.wakeup, WSSC);
+      do
+       {
+         rc = cygwait (pack.wakeup, WSSC, cw_sig_eintr);
+         if (rc == WAIT_SIGNALED && pack.si.si_signo != __SIGFLUSHFAST)
+           _my_tls.call_signal_handler ();
+       }
+      while (rc != WAIT_OBJECT_0 && rc != WAIT_TIMEOUT);
+      /* Re-assert signal_arrived which has been cleared in cygwait(). */
+      if (_my_tls.current_sig)
+       _my_tls.set_signal_arrived ();
       ForceCloseHandle (pack.wakeup);
     }
   else
@@ -806,9 +819,6 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
       rc = -1;
     }
 
-  if (wait_for_completion && si.si_signo != __SIGFLUSHFAST)
-    _my_tls.call_signal_handler ();
-
 out:
   if (communing && rc)
     {

Reply via email to