Previously, sig thread ran in THREAD_PRIORITY_HIGHEST priority. This caused critical delay in signal handling in the main thread if the too many signales are received rapidly and CPU is very busy. I this case, most of CPU time is allocated to sig thread, so the main thread cannot have a chance to handle signals. With this patch, the sig thread priority is set to the same priority with main thread to avoid such situation. Furthermore, if the signal is alarted to the main thread, but main thread does not handle it yet, in order to increase the chance to handle it in the main thread, reduce the sig thread priority is to THREAD_PRIORITY_LOWEST temporarily.
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: Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp> --- winsup/cygwin/sigproc.cc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index b8d961a07..fc4360951 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -1319,6 +1319,23 @@ wait_sig (VOID *) { DWORD nb; sigpacket pack = {}; + /* Follow to the main thread priority */ + int prio = THREAD_PRIORITY_NORMAL; + if (cygwin_finished_initializing) + { + HANDLE h_main_thread = NULL; + threadlist_t *tl_entry = cygheap->find_tls (_main_tls); + if (_main_tls->thread_id) + h_main_thread = OpenThread (THREAD_QUERY_INFORMATION, + FALSE, _main_tls->thread_id); + cygheap->unlock_tls (tl_entry); + if (h_main_thread) + { + prio = GetThreadPriority (h_main_thread); + CloseHandle (h_main_thread); + } + } + SetThreadPriority (GetCurrentThread (), prio); if (sigq.retry) pack.si.si_signo = __SIGFLUSH; else if (sigq.start.next @@ -1331,6 +1348,15 @@ wait_sig (VOID *) system_printf ("garbled signal pipe data nb %u, sig %d", nb, pack.si.si_signo); continue; } + if (cygwin_finished_initializing) + { + threadlist_t *tl_entry = cygheap->find_tls (_main_tls); + if (_main_tls->current_sig) + /* Decrease the priority in order to make main thread process + this signal. */ + SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_LOWEST); + cygheap->unlock_tls (tl_entry); + } sigq.retry = false; /* Don't process signals when we start exiting */ -- 2.45.1