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:
parent
656a84e180
commit
643f2884cc
1 changed files with 8 additions and 1 deletions
|
|
@ -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!
|
||||
|
|
|
|||
Loading…
Reference in a new issue