From 33799c250f0a7d353cfc34961c7bba26d3a4219a Mon Sep 17 00:00:00 2001 From: Takashi Yano Date: Mon, 23 Dec 2024 10:33:25 +0900 Subject: [PATCH] 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. Applied-from: https://inbox.sourceware.org/cygwin-patches/20241223013332.1269-1-takashi.yano@nifty.ne.jp 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 Reviewed-by: Signed-off-by: Takashi Yano Signed-off-by: Johannes Schindelin --- winsup/cygwin/release/3.5.6 | 5 +++++ winsup/cygwin/sigproc.cc | 20 +++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 winsup/cygwin/release/3.5.6 diff --git a/winsup/cygwin/release/3.5.6 b/winsup/cygwin/release/3.5.6 new file mode 100644 index 0000000000..643d58e585 --- /dev/null +++ b/winsup/cygwin/release/3.5.6 @@ -0,0 +1,5 @@ +Fixes: +------ + +- 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 cf43aa9335..c2985277fc 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.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.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) {