Previously, the sig thread ran in THREAD_PRIORITY_HIGHEST priority.
This causes a critical delay in the signal handling in the main
thread if too many signals are received rapidly and the CPU is very
busy. In this case, most of the CPU time is allocated to the sig
thread, so the main thread cannot have a chance of handling signals.
With this patch, to avoid such a situation, the priority of the sig
thread is set to THREAD_PRIORITY_NORMAL priority. Furthermore, if
the signal is alerted to the main thread, but the main thread does
not handle it yet, to increase the chance of handling it in the main
thread, reduce the sig thread priority to THREAD_PRIORITY_LOWEST
priority temporarily before calling _cygtls::handle_SIGCONT().

Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256744.html
Fixes: 53ad6f1394aa ("(cygthread::cygthread): Use three only arguments for 
detached threads, and start the thread via QueueUserAPC/async_create.")
Reported-by: Christian Franke <christian.fra...@t-online.de>
Reviewed-by: Corinna Vinschen <cori...@vinschen.de>
Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp>
---
 winsup/cygwin/exceptions.cc | 6 ++++++
 winsup/cygwin/sigproc.cc    | 1 +
 2 files changed, 7 insertions(+)

diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 0f8c21939..7fc644af1 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -978,6 +978,9 @@ sigpacket::setup_handler (void *handler, struct sigaction& 
siga, _cygtls *tls)
   CONTEXT cx;
   bool interrupted = false;
 
+  for (int i = 0; i < 100 && tls->current_sig; i++)
+    yield ();
+
   if (tls->current_sig)
     {
       sigproc_printf ("trying to send signal %d but signal %d already armed",
@@ -1482,7 +1485,10 @@ sigpacket::process ()
   if (si.si_signo == SIGCONT)
     {
       tl_entry = cygheap->find_tls (_main_tls);
+      if (_main_tls->current_sig)
+       SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_LOWEST);
       _main_tls->handle_SIGCONT (tl_entry);
+      SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL);
       cygheap->unlock_tls (tl_entry);
     }
 
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 8ffb90a2c..8c788bd20 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -1332,6 +1332,7 @@ wait_sig (VOID *)
 
   hntdll = GetModuleHandle ("ntdll.dll");
 
+  SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_NORMAL);
   for (;;)
     {
       DWORD nb;
-- 
2.45.1

Reply via email to