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 to handle signals. With this patch, the sig thread priority is set to the same priority as the main thread to avoid such a situation. Furthermore, if the signal is alerted to the main thread, but the main thread does not handle it yet, in order to increase the chance of handling it in the main thread, reduce the sig thread priority 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