Skip to content

Commit 39373fe

Browse files
committed
Cygwin: signal: Do not handle signals while waiting for wakeup evt
... Otherwise, the opportunity for cleanup the wakeup event handle etc. may be lost because the user signal handler never returns if it calls longjmp(). This results in handle leak because the wakeup event handle will not be closed. This issue happens when the commnad e.g. "stress-ng --mprotect 1 -t 5" is executed. Instead, call call_signal_handler() after cleaning up if some signals are armed during waiting wakeup event. This essentially reverts the commit d243e51, however, the deadlock fixed by that commit no longer occurs even reverting it for some reason. This is probably due to the redesign of the signal queue. In addition, do not touch "incyg" flag in _cygtls::call_signal_handler() because the process is still in the cygwin function when a user signal handler is called from the cygwin functions such as cygwait(). Addresses: https://sourceware.org/pipermail/cygwin/2025-March/257726.html Fixes: d243e51 ("Cygwin: signal: Fix deadlock between main thread and sig thread") Fixes: 3a1ccfc ("* exceptions.cc (setup_handler): Remove locked flag. Use 'incyg' flag and in_exception function to determine when we're in a cygwin function.") Reported-by: Christian Franke <[email protected]> Signed-off-by: Takashi Yano <[email protected]> (cherry picked from commit 68991cd)
1 parent 2b98cc8 commit 39373fe

File tree

2 files changed

+11
-12
lines changed

2 files changed

+11
-12
lines changed

winsup/cygwin/exceptions.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,7 +1756,6 @@ _cygtls::call_signal_handler ()
17561756

17571757
int this_errno = saved_errno;
17581758
reset_signal_arrived ();
1759-
incyg = false;
17601759
current_sig = 0; /* Flag that we can accept another signal */
17611760

17621761
/* We have to fetch the original return address from the signal stack
@@ -1869,8 +1868,6 @@ _cygtls::call_signal_handler ()
18691868
}
18701869
unlock ();
18711870

1872-
incyg = true;
1873-
18741871
set_signal_mask (_my_tls.sigmask, (this_sa_flags & SA_SIGINFO)
18751872
? context1.uc_sigmask : this_oldmask);
18761873
if (this_errno >= 0)

winsup/cygwin/sigproc.cc

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
611611
bool communing = si.si_signo == __SIGCOMMUNE;
612612

613613
pack.wakeup = NULL;
614-
bool wait_for_completion;
614+
bool wait_for_completion = false;
615615
if (!(its_me = p == NULL || p == myself || p == myself_nowait))
616616
{
617617
/* It is possible that the process is not yet ready to receive messages
@@ -762,13 +762,10 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
762762
memcpy (p, si._si_commune._si_str, n); p += n;
763763
}
764764

765-
unsigned cw_mask;
766-
cw_mask = pack.si.si_signo == __SIGFLUSHFAST ? 0 : cw_sig_restart;
767-
768765
char mtx_name[MAX_PATH];
769766
shared_name (mtx_name, "sig_send", p->pid);
770767
mtx = CreateMutex (&sec_none_nih, FALSE, mtx_name);
771-
cygwait (mtx, INFINITE, cw_mask);
768+
WaitForSingleObject (mtx, INFINITE);
772769

773770
if (its_me && (si.si_signo == __SIGFLUSHFAST || si.si_signo == __SIGFLUSH))
774771
{
@@ -791,7 +788,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
791788
CloseHandle (mtx);
792789
ResetEvent (sigflush_done_evt);
793790
SetEvent (sigflush_evt);
794-
cygwait (sigflush_done_evt, INFINITE, cw_mask);
791+
WaitForSingleObject (sigflush_done_evt, INFINITE);
795792
rc = 0;
796793
goto out;
797794
}
@@ -807,8 +804,8 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
807804
if (!res || packsize == nb)
808805
break;
809806
ReleaseMutex (mtx);
810-
cygwait (NULL, 10, cw_mask);
811-
cygwait (mtx, INFINITE, cw_mask);
807+
Sleep (10);
808+
WaitForSingleObject (mtx, INFINITE);
812809
res = 0;
813810
}
814811
ReleaseMutex (mtx);
@@ -843,7 +840,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
843840
if (wait_for_completion)
844841
{
845842
sigproc_printf ("Waiting for pack.wakeup %p", pack.wakeup);
846-
rc = cygwait (pack.wakeup, WSSC, cw_mask);
843+
rc = WaitForSingleObject (pack.wakeup, WSSC);
847844
ForceCloseHandle (pack.wakeup);
848845
}
849846
else
@@ -874,6 +871,11 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
874871
}
875872
if (pack.wakeup)
876873
ForceCloseHandle (pack.wakeup);
874+
875+
/* Handle signals here if it was not handled yet */
876+
if (wait_for_completion && pack.si.si_signo != __SIGFLUSHFAST)
877+
_my_tls.call_signal_handler ();
878+
877879
if (si.si_signo != __SIGPENDING && si.si_signo != __SIGPENDINGALL)
878880
/* nothing */;
879881
else if (!rc)

0 commit comments

Comments
 (0)