LibCore: Fix signal handler deadlock in EventLoopImplementationUnix

handle_signal() called ThreadData::the() which can acquire a write
lock on s_thread_data_lock if the thread hasn't initialized its
ThreadData yet. If the signal interrupts a thread that already holds
a read lock on s_thread_data_lock (e.g. in unregister_notifier()),
this deadlocks — the write lock waits for the read lock, but the
read lock holder is blocked in the signal handler.

Fix by accessing the thread-local s_this_thread_data directly. If
the thread has no ThreadData, there's no wake pipe to write to, so
we just return.
This commit is contained in:
Andreas Kling
2026-03-07 12:04:57 +01:00
committed by Andreas Kling
parent 656a84e180
commit 643f2884cc
Notes: github-actions[bot] 2026-03-07 12:10:59 +00:00

View File

@@ -565,7 +565,14 @@ bool SignalHandlers::remove(int handler_id)
void EventLoopManagerUnix::handle_signal(int signal_number)
{
VERIFY(signal_number != 0);
auto& thread_data = ThreadData::the();
// Use the thread-local directly instead of ThreadData::the() to avoid
// taking a write lock on s_thread_data_lock. Signal handlers must not
// acquire locks, as we may already be holding one on this thread.
if (!s_this_thread_data)
return;
auto& thread_data = *s_this_thread_data;
// We MUST check if the current pid still matches, because there
// is a window between fork() and exec() where a signal delivered
// to our fork could be inadvertently routed to the parent process!