[llvm] [Support] Don't take a lock in CrashRecoverySignalHandler (PR #219529)

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 28 09:54:56 PDT 2026


https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/219529

Disable() locks a mutex with static storage duration, which is not safe from a signal handler. When the signal arrives during exit(), after static destructors have run, the mutex is already destroyed, pthread_mutex_lock returns EINVAL causing libc++ to throw.

To make matters worse, without exceptions, the throw becomes a std::terminate, which happens before uninstallExceptionOrSignalHandlers. Because the signal handler is installed without SA_RESETHAND, every call to abort() re-enters the handler and throws again.

Inline the two statements Disable() performs. Racing with another thread here doesn't matter, as the previous comment noted.

>From 6c0815197f1cf1bf8e0b6417c73636049fa6b318 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Fri, 28 Aug 2026 09:48:29 -0700
Subject: [PATCH] [Support] Don't take a lock in CrashRecoverySignalHandler

Disable() locks a mutex with static storage duration, which is not safe
from a signal handler. When the signal arrives during exit(), after
static destructors have run, the mutex is already destroyed,
pthread_mutex_lock returns EINVAL causing libc++ to throw.

To make matters worse, without exceptions, the throw becomes a
std::terminate, which happens before uninstallExceptionOrSignalHandlers.
Because the signal handler is installed without SA_RESETHAND, every call
to abort() re-enters the handler and throws again.

Inline the two statements Disable() performs. Racing with another thread
here doesn't matter, as the previous comment noted.
---
 llvm/lib/Support/CrashRecoveryContext.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index 493ba951fd3e1..c4bad21fcefc3 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -369,8 +369,12 @@ static void CrashRecoverySignalHandler(int Signal) {
     // that the enclosing application will terminate soon, and we won't want to
     // attempt crash recovery again.
     //
-    // This call of Disable isn't thread safe, but it doesn't actually matter.
-    CrashRecoveryContext::Disable();
+    // Uninstall directly rather than through Disable(): a signal handler must
+    // not take a lock, and a lock with static storage duration may already be
+    // destroyed by the time a signal is delivered during exit(). Racing with
+    // another thread here doesn't matter.
+    gCrashRecoveryEnabled = false;
+    uninstallExceptionOrSignalHandlers();
     raise(Signal);
 
     // The signal will be thrown once the signal mask is restored.



More information about the llvm-commits mailing list