[clang] [clang-tools-extra] [llvm] [LLVM][CLANG] Update signal-handling behavior to comply with POSIX (PR #169340)
Xing Xue via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 9 09:52:17 PST 2026
https://github.com/xingxue-ibm updated https://github.com/llvm/llvm-project/pull/169340
>From b79cb89b75d0892a2e41fdf1fafa6e3b6a422280 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Fri, 21 Nov 2025 15:29:56 -0500
Subject: [PATCH 01/10] Don't install signal handler if the disposition of a
signal is SIG_IGN, resignal after the signal handler handles a signal so the
exit code of the compiler contains the signal number.
---
.../unittests/ThreadCrashReporterTests.cpp | 12 +++++++++
clang/lib/Driver/Driver.cpp | 7 +++++
clang/tools/driver/driver.cpp | 18 ++++++++++++-
llvm/lib/Support/CrashRecoveryContext.cpp | 6 ++++-
llvm/lib/Support/Unix/Signals.inc | 27 ++++++++++++-------
5 files changed, 58 insertions(+), 12 deletions(-)
diff --git a/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp b/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
index 0eb8d472c6702..1c86fcbea4a4b 100644
--- a/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
@@ -13,6 +13,17 @@
#include <csignal>
#include <string>
+// According to the POSIX specification, if the inherited disposition of a
+// signal is the default action, the behavior of utilitys must be as if the
+// default action had been taken. When the required default action is to
+// terminate the process, such as for SIGUSR1, the utility may catch the
+// signal, perform additional processing, restore the default disposition,
+// and then re-signal itself. This causes the process to terminate as
+// required. Because of this behavior, the crash-reporter test here is not
+// suitable for Unix platforms.
+
+#ifndef LLVM_ON_UNIX
+
namespace clang {
namespace clangd {
@@ -76,3 +87,4 @@ TEST(ThreadCrashReporterTest, All) {
} // namespace
} // namespace clangd
} // namespace clang
+#endif // !LLVM_ON_UNIX
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index a55c5033b57cf..e364d1efaeeec 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2316,7 +2316,14 @@ int Driver::ExecuteCompilation(
if (!FailingCommand->getCreator().hasGoodDiagnostics() || CommandRes != 1) {
// FIXME: See FIXME above regarding result code interpretation.
+#if LLVM_ON_UNIX
+ // On Unix, signals are represented by return codes of 128 plus the
+ // signal number. Return code 255 is excluded because some tools,
+ // such as llvm-ifs, exit with code 255 (-1) on failure.
+ if (CommandRes > 128 && CommandRes != 255)
+#else
if (CommandRes < 0)
+#endif
Diag(clang::diag::err_drv_command_signalled)
<< FailingTool.getShortName();
else
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index 490136961ebc6..a586494cdc8a9 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -55,6 +55,9 @@
#include <optional>
#include <set>
#include <system_error>
+#if LLVM_ON_UNIX
+#include <signal.h>
+#endif
using namespace clang;
using namespace clang::driver;
@@ -407,6 +410,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
Driver::CommandStatus CommandStatus = Driver::CommandStatus::Ok;
// Pretend the first command failed if ReproStatus is Always.
const Command *FailingCommand = nullptr;
+ int CommandRes = 0;
if (!C->getJobs().empty())
FailingCommand = &*C->getJobs().begin();
if (C && !C->containsError()) {
@@ -414,7 +418,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
for (const auto &P : FailingCommands) {
- int CommandRes = P.first;
+ CommandRes = P.first;
FailingCommand = P.second;
if (!Res)
Res = CommandRes;
@@ -471,6 +475,18 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
Res = 1;
#endif
+#if LLVM_ON_UNIX
+ // On Unix, signals are represented by return codes of 128 plus the signal
+ // number. If the return code indicates it was from a signal handler, raise
+ // the signal so that the exit code includes the signal number, as required
+ // by POSIX. Return code 255 is excluded because some tools, such as
+ // llvm-ifs, exit with code 255 (-1) on failure.
+ if (CommandRes > 128 && CommandRes != 255) {
+ llvm::sys::unregisterHandlers();
+ raise(CommandRes - 128);
+ }
+#endif
+
// If we have multiple failing commands, we return the result of the first
// failing command.
return Res;
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index 1ba0c2383daec..c6bfa4d0245da 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -398,7 +398,11 @@ static void installExceptionOrSignalHandlers() {
sigemptyset(&Handler.sa_mask);
for (unsigned i = 0; i != NumSignals; ++i) {
- sigaction(Signals[i], &Handler, &PrevActions[i]);
+ struct sigaction act;
+ sigaction(Signals[i], NULL, &act);
+ // Don't install signal handler if the disposition of a signal is SIG_IGN.
+ if (act.sa_handler != SIG_IGN)
+ sigaction(Signals[i], &Handler, &PrevActions[i]);
}
}
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 56ad4fc504153..35ac441d73be8 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -327,8 +327,12 @@ static void RegisterHandlers() { // Not signal-safe.
}
sigemptyset(&NewHandler.sa_mask);
- // Install the new handler, save the old one in RegisteredSignalInfo.
- sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
+ // Install the new handler if the signal disposition isn't SIG_IGN,
+ // save the old one in RegisteredSignalInfo.
+ struct sigaction act;
+ sigaction(Signal, NULL, &act);
+ if (act.sa_handler != SIG_IGN)
+ sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
RegisteredSignalInfo[Index].SigNo = Signal;
++NumRegisteredSignals;
};
@@ -411,14 +415,12 @@ static void SignalHandler(int Sig, siginfo_t *Info, void *) {
// Otherwise if it is a fault (like SEGV) run any handler.
llvm::sys::RunSignalHandlers();
-#ifdef __s390__
- // On S/390, certain signals are delivered with PSW Address pointing to
- // *after* the faulting instruction. Simply returning from the signal
- // handler would continue execution after that point, instead of
- // re-raising the signal. Raise the signal manually in those cases.
- if (Sig == SIGILL || Sig == SIGFPE || Sig == SIGTRAP)
- raise(Sig);
-#endif
+ // Resignal if it is a kill signal so that the exit code contains the
+ // terminating signal number.
+ if (llvm::is_contained(KillSigs, Sig)) {
+ raise(Sig); // Execute the default handler.
+ return;
+ }
#if defined(__linux__)
// Re-raising a signal via `raise` loses the original siginfo. Recent
@@ -441,6 +443,11 @@ static void InfoSignalHandler(int Sig) {
SaveAndRestore SaveErrnoDuringASignalHandler(errno);
if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction)
CurrentInfoFunction();
+
+ if (Sig == SIGUSR1) {
+ sys::unregisterHandlers();
+ raise(Sig);
+ }
}
void sys::RunInterruptHandlers() {
>From ff86338f168dcf39ae6a50ddea3fdfdeba47d2a9 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Fri, 9 Jan 2026 12:41:58 -0500
Subject: [PATCH 02/10] Address comments to only change the Clang's behavior
according to the POSIX specification for utilities. Update test cases to
reflect they failed because of signal/crash.
---
.../unittests/ThreadCrashReporterTests.cpp | 12 ------------
clang/test/Driver/crash-diagnostics-dir-3.c | 2 +-
clang/test/Driver/crash-diagnostics-dir.c | 2 +-
clang/test/Driver/crash-ir-repro.cpp | 2 +-
clang/test/Driver/crash-report-clang-cl.cpp | 2 +-
clang/test/Driver/crash-report-header.h | 2 +-
clang/test/Driver/crash-report-spaces.c | 2 +-
clang/test/Driver/crash-report-with-asserts.c | 4 ++--
clang/test/Driver/crash-report.cpp | 4 ++--
clang/test/Driver/emit-reproducer.c | 14 +++++++-------
clang/test/Driver/output-file-cleanup.c | 2 +-
llvm/cmake/modules/AddLLVM.cmake | 7 +++++++
.../cmake/modules/llvm-driver-template.cpp.in | 2 +-
llvm/include/llvm/Support/InitLLVM.h | 8 +++++---
llvm/include/llvm/Support/Signals.h | 2 +-
llvm/lib/Support/InitLLVM.cpp | 5 +++--
llvm/lib/Support/Unix/Signals.inc | 19 +++++++++++++++----
17 files changed, 50 insertions(+), 41 deletions(-)
diff --git a/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp b/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
index 1c86fcbea4a4b..0eb8d472c6702 100644
--- a/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ThreadCrashReporterTests.cpp
@@ -13,17 +13,6 @@
#include <csignal>
#include <string>
-// According to the POSIX specification, if the inherited disposition of a
-// signal is the default action, the behavior of utilitys must be as if the
-// default action had been taken. When the required default action is to
-// terminate the process, such as for SIGUSR1, the utility may catch the
-// signal, perform additional processing, restore the default disposition,
-// and then re-signal itself. This causes the process to terminate as
-// required. Because of this behavior, the crash-reporter test here is not
-// suitable for Unix platforms.
-
-#ifndef LLVM_ON_UNIX
-
namespace clang {
namespace clangd {
@@ -87,4 +76,3 @@ TEST(ThreadCrashReporterTest, All) {
} // namespace
} // namespace clangd
} // namespace clang
-#endif // !LLVM_ON_UNIX
diff --git a/clang/test/Driver/crash-diagnostics-dir-3.c b/clang/test/Driver/crash-diagnostics-dir-3.c
index a91bc48d7e462..8d22df85abd2f 100644
--- a/clang/test/Driver/crash-diagnostics-dir-3.c
+++ b/clang/test/Driver/crash-diagnostics-dir-3.c
@@ -1,6 +1,6 @@
// RUN: export LSAN_OPTIONS=detect_leaks=0
// RUN: rm -rf %t
-// RUN: not env CLANG_CRASH_DIAGNOSTICS_DIR=%t %clang -c %s -o - 2>&1 | FileCheck %s
+// RUN: not --crash env CLANG_CRASH_DIAGNOSTICS_DIR=%t %clang -c %s -o - 2>&1 | FileCheck %s
#pragma clang __debug parser_crash
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir-3.c.tmp{{(/|\\).*}}.c
diff --git a/clang/test/Driver/crash-diagnostics-dir.c b/clang/test/Driver/crash-diagnostics-dir.c
index 16382eff1cde7..56c77beae7234 100644
--- a/clang/test/Driver/crash-diagnostics-dir.c
+++ b/clang/test/Driver/crash-diagnostics-dir.c
@@ -1,6 +1,6 @@
// RUN: export LSAN_OPTIONS=detect_leaks=0
// RUN: rm -rf %t
-// RUN: not %clang -fcrash-diagnostics-dir=%t -c %s -o - 2>&1 | FileCheck %s
+// RUN: not --crash %clang -fcrash-diagnostics-dir=%t -c %s -o - 2>&1 | FileCheck %s
#pragma clang __debug parser_crash
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c
diff --git a/clang/test/Driver/crash-ir-repro.cpp b/clang/test/Driver/crash-ir-repro.cpp
index 217d5ed421bdb..9d40238e76a23 100644
--- a/clang/test/Driver/crash-ir-repro.cpp
+++ b/clang/test/Driver/crash-ir-repro.cpp
@@ -1,5 +1,5 @@
// RUN: %clang -S -emit-llvm -o %t.ll %s
-// RUN: not %clang -S -DCRASH %s -o %t.ll 2>&1 | FileCheck %s
+// RUN: not --crash %clang -S -DCRASH %s -o %t.ll 2>&1 | FileCheck %s
// TODO(boomanaiden154): This test case causes clang to raise a signal when
// running under ubsan, but not in normal build configurations. This should
diff --git a/clang/test/Driver/crash-report-clang-cl.cpp b/clang/test/Driver/crash-report-clang-cl.cpp
index 963c3b6d0ab03..3efeb8088db52 100644
--- a/clang/test/Driver/crash-report-clang-cl.cpp
+++ b/clang/test/Driver/crash-report-clang-cl.cpp
@@ -2,7 +2,7 @@
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: not %clang_cl -fsyntax-only /Brepro /source-charset:utf-8 \
+// RUN: not --crash %clang_cl -fsyntax-only /Brepro /source-charset:utf-8 \
// RUN: -fcrash-diagnostics-dir=%t -- %s 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-clang-cl-*.cpp | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-clang-cl-*.sh | FileCheck --check-prefix=CHECKSH %s
diff --git a/clang/test/Driver/crash-report-header.h b/clang/test/Driver/crash-report-header.h
index 04865a0cc300f..31c71ff625c05 100644
--- a/clang/test/Driver/crash-report-header.h
+++ b/clang/test/Driver/crash-report-header.h
@@ -1,7 +1,7 @@
// RUN: export LSAN_OPTIONS=detect_leaks=0
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not --crash %clang -fsyntax-only %s 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-header-*.h | FileCheck --check-prefix=CHECKSRC "%s"
// RUN: cat %t/crash-report-header-*.sh | FileCheck --check-prefix=CHECKSH "%s"
// REQUIRES: crash-recovery
diff --git a/clang/test/Driver/crash-report-spaces.c b/clang/test/Driver/crash-report-spaces.c
index b4d8ac1f57e83..c01c8df0552de 100644
--- a/clang/test/Driver/crash-report-spaces.c
+++ b/clang/test/Driver/crash-report-spaces.c
@@ -2,7 +2,7 @@
// RUN: rm -rf "%t"
// RUN: mkdir "%t"
// RUN: cp "%s" "%t/crash report spaces.c"
-// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s"
+// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not --crash %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s"
// RUN: cat "%t/crash report spaces"-*.c | FileCheck --check-prefix=CHECKSRC "%s"
// RUN: cat "%t/crash report spaces"-*.sh | FileCheck --check-prefix=CHECKSH "%s"
// REQUIRES: crash-recovery
diff --git a/clang/test/Driver/crash-report-with-asserts.c b/clang/test/Driver/crash-report-with-asserts.c
index 686c49f339fb7..0b619d9ec2f46 100644
--- a/clang/test/Driver/crash-report-with-asserts.c
+++ b/clang/test/Driver/crash-report-with-asserts.c
@@ -12,13 +12,13 @@
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not %clang %s @%t.rsp -DASSERT 2>&1 | FileCheck %s
+// RUN: not --crash %clang %s @%t.rsp -DASSERT 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not %clang %s @%t.rsp -DUNREACHABLE 2>&1 | FileCheck %s
+// RUN: not --crash %clang %s @%t.rsp -DUNREACHABLE 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-with-asserts-*.c | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-with-asserts-*.sh | FileCheck --check-prefix=CHECKSH %s
diff --git a/clang/test/Driver/crash-report.cpp b/clang/test/Driver/crash-report.cpp
index 59eee65af57ee..4b5adfc02bff4 100644
--- a/clang/test/Driver/crash-report.cpp
+++ b/clang/test/Driver/crash-report.cpp
@@ -12,13 +12,13 @@
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not %clang %s @%t.rsp -DPARSER 2>&1 | FileCheck %s
+// RUN: not --crash %clang %s @%t.rsp -DPARSER 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-*.cpp | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not %clang %s @%t.rsp -DCRASH 2>&1 | FileCheck %s
+// RUN: not --crash %clang %s @%t.rsp -DCRASH 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-*.cpp | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
diff --git a/clang/test/Driver/emit-reproducer.c b/clang/test/Driver/emit-reproducer.c
index 18e1b4e41b91d..28c585193a7d0 100644
--- a/clang/test/Driver/emit-reproducer.c
+++ b/clang/test/Driver/emit-reproducer.c
@@ -3,13 +3,13 @@
// RUN: echo "%s -fcrash-diagnostics-dir=%t -fsyntax-only" | sed -e 's/\\/\\\\/g' > %t.rsp
-// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT
-// RUN: not %clang -DFATAL @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT
-// RUN: not %clang -DFATAL @%t.rsp 2>&1 | FileCheck %s
-// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=crash 2>&1 | FileCheck %s
-// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=error 2>&1 | FileCheck %s
-// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer=always 2>&1 | FileCheck %s
-// RUN: not %clang -DFATAL @%t.rsp -gen-reproducer 2>&1 | FileCheck %s
+// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT
+// RUN: not --crash %clang -DFATAL @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT
+// RUN: not --crash %clang -DFATAL @%t.rsp 2>&1 | FileCheck %s
+// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=crash 2>&1 | FileCheck %s
+// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=error 2>&1 | FileCheck %s
+// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=always 2>&1 | FileCheck %s
+// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer 2>&1 | FileCheck %s
// RUN: not %clang -DERROR @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT
// RUN: not %clang -DERROR @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT
diff --git a/clang/test/Driver/output-file-cleanup.c b/clang/test/Driver/output-file-cleanup.c
index 3628df8192652..b5f548dc0b01a 100644
--- a/clang/test/Driver/output-file-cleanup.c
+++ b/clang/test/Driver/output-file-cleanup.c
@@ -2,7 +2,7 @@
// RUN: rm -f "%t.d" "%t1.s" "%t2.s" "%t3.s" "%t4.s" "%t5.s"
//
// RUN: touch %t.s
-// RUN: not %clang -S -DCRASH -o %t.s -MMD -MF %t.d %s
+// RUN: not --crash %clang -S -DCRASH -o %t.s -MMD -MF %t.d %s
// RUN: test ! -f %t.s
// RUN: test ! -f %t.d
diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index d938214f9d0df..b4ca46a874067 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -1004,6 +1004,13 @@ macro(generate_llvm_objects name)
if (ARG_GENERATE_DRIVER)
string(REPLACE "-" "_" TOOL_NAME ${name})
+
+ set(INITLLVM_ARGS "")
+
+ if(${name} STREQUAL "clang")
+ set(INITLLVM_ARGS ", /*InstallPipeSignalExitHandler=*/true, /*IsClangDriver=*/true")
+ endif()
+
foreach(path ${CMAKE_MODULE_PATH})
if(EXISTS ${path}/llvm-driver-template.cpp.in)
configure_file(
diff --git a/llvm/cmake/modules/llvm-driver-template.cpp.in b/llvm/cmake/modules/llvm-driver-template.cpp.in
index 1470ef1f06164..d4c385c8cf412 100644
--- a/llvm/cmake/modules/llvm-driver-template.cpp.in
+++ b/llvm/cmake/modules/llvm-driver-template.cpp.in
@@ -13,6 +13,6 @@
int @TOOL_NAME at _main(int argc, char **, const llvm::ToolContext &);
int main(int argc, char **argv) {
- llvm::InitLLVM X(argc, argv);
+ llvm::InitLLVM X(argc, argv at INITLLVM_ARGS@);
return @TOOL_NAME at _main(argc, argv, {argv[0], nullptr, false});
}
diff --git a/llvm/include/llvm/Support/InitLLVM.h b/llvm/include/llvm/Support/InitLLVM.h
index 748f5d8aa6aea..1473026e2974a 100644
--- a/llvm/include/llvm/Support/InitLLVM.h
+++ b/llvm/include/llvm/Support/InitLLVM.h
@@ -36,10 +36,12 @@ namespace llvm {
class InitLLVM {
public:
LLVM_ABI InitLLVM(int &Argc, const char **&Argv,
- bool InstallPipeSignalExitHandler = true);
- InitLLVM(int &Argc, char **&Argv, bool InstallPipeSignalExitHandler = true)
+ bool InstallPipeSignalExitHandler = true,
+ bool IsClandDriver = false);
+ InitLLVM(int &Argc, char **&Argv, bool InstallPipeSignalExitHandler = true,
+ bool IsClangDriver = false)
: InitLLVM(Argc, const_cast<const char **&>(Argv),
- InstallPipeSignalExitHandler) {}
+ InstallPipeSignalExitHandler, IsClangDriver) {}
LLVM_ABI ~InitLLVM();
diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h
index 21b425fffef53..22612a55b3a37 100644
--- a/llvm/include/llvm/Support/Signals.h
+++ b/llvm/include/llvm/Support/Signals.h
@@ -100,7 +100,7 @@ using SignalHandlerCallback = void (*)(void *);
/// Add a function to be called when an abort/kill signal is delivered to the
/// process. The handler can have a cookie passed to it to identify what
/// instance of the handler it is.
-LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie);
+LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie, bool IsClangDriver = false);
/// This function registers a function to be called when the user "interrupts"
/// the program (typically by pressing ctrl-c). When the user interrupts the
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index b90f4e0714458..248250cc5ddcb 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -73,7 +73,8 @@ using namespace llvm;
using namespace llvm::sys;
InitLLVM::InitLLVM(int &Argc, const char **&Argv,
- bool InstallPipeSignalExitHandler) {
+ bool InstallPipeSignalExitHandler,
+ bool IsClangDriver) {
#ifndef NDEBUG
static std::atomic<bool> Initialized{false};
assert(!Initialized && "InitLLVM was already initialized!");
@@ -81,7 +82,7 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
#endif
// Bring stdin/stdout/stderr into a known state.
- sys::AddSignalHandler(CleanupStdHandles, nullptr);
+ sys::AddSignalHandler(CleanupStdHandles, nullptr, IsClangDriver);
if (InstallPipeSignalExitHandler)
// The pipe signal handler must be installed before any other handlers are
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 35ac441d73be8..1d1cc9c915a72 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -86,6 +86,7 @@ using namespace llvm;
static void SignalHandler(int Sig, siginfo_t *Info, void *);
static void InfoSignalHandler(int Sig); // defined below.
+static void InfoSignalHandlerTerminate(int Sig); // defined below.
using SignalHandlerFunctionType = void (*)();
/// The function to call if ctrl-c is pressed.
@@ -292,7 +293,7 @@ static void CreateSigAltStack() {
static void CreateSigAltStack() {}
#endif
-static void RegisterHandlers() { // Not signal-safe.
+static void RegisterHandlers(bool IsClangDriver = false) { // Not signal-safe.
// The mutex prevents other threads from registering handlers while we're
// doing it. We also have to protect the handlers and their count because
// a signal handler could fire while we're registering handlers.
@@ -321,7 +322,12 @@ static void RegisterHandlers() { // Not signal-safe.
NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK | SA_SIGINFO;
break;
case SignalKind::IsInfo:
- NewHandler.sa_handler = InfoSignalHandler;
+ if (IsClangDriver)
+ // If it is the Clang driver the signal handler resignal itself to
+ // terminate after handling the signal.
+ NewHandler.sa_handler = InfoSignalHandlerTerminate;
+ else
+ NewHandler.sa_handler = InfoSignalHandler;
NewHandler.sa_flags = SA_ONSTACK;
break;
}
@@ -443,6 +449,10 @@ static void InfoSignalHandler(int Sig) {
SaveAndRestore SaveErrnoDuringASignalHandler(errno);
if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction)
CurrentInfoFunction();
+}
+
+static void InfoSignalHandlerTerminate(int Sig) {
+ InfoSignalHandler(Sig);
if (Sig == SIGUSR1) {
sys::unregisterHandlers();
@@ -496,9 +506,10 @@ void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {
/// handler can have a cookie passed to it to identify what instance of the
/// handler it is.
void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
- void *Cookie) { // Signal-safe.
+ void *Cookie, bool IsClangDriver) {
+ // Signal-safe.
insertSignalHandler(FnPtr, Cookie);
- RegisterHandlers();
+ RegisterHandlers(IsClangDriver);
}
#if ENABLE_BACKTRACES && defined(HAVE_BACKTRACE) && \
>From ec229ade8743b31d3c546d54cdf874a49134114d Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Fri, 9 Jan 2026 12:52:48 -0500
Subject: [PATCH 03/10] Fix formatting.
---
llvm/include/llvm/Support/InitLLVM.h | 2 +-
llvm/include/llvm/Support/Signals.h | 3 ++-
llvm/lib/Support/InitLLVM.cpp | 3 +--
llvm/lib/Support/Unix/Signals.inc | 6 +++---
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/llvm/include/llvm/Support/InitLLVM.h b/llvm/include/llvm/Support/InitLLVM.h
index 1473026e2974a..6859964bd8f22 100644
--- a/llvm/include/llvm/Support/InitLLVM.h
+++ b/llvm/include/llvm/Support/InitLLVM.h
@@ -39,7 +39,7 @@ class InitLLVM {
bool InstallPipeSignalExitHandler = true,
bool IsClandDriver = false);
InitLLVM(int &Argc, char **&Argv, bool InstallPipeSignalExitHandler = true,
- bool IsClangDriver = false)
+ bool IsClangDriver = false)
: InitLLVM(Argc, const_cast<const char **&>(Argv),
InstallPipeSignalExitHandler, IsClangDriver) {}
diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h
index 22612a55b3a37..9d8fa97eb50b5 100644
--- a/llvm/include/llvm/Support/Signals.h
+++ b/llvm/include/llvm/Support/Signals.h
@@ -100,7 +100,8 @@ using SignalHandlerCallback = void (*)(void *);
/// Add a function to be called when an abort/kill signal is delivered to the
/// process. The handler can have a cookie passed to it to identify what
/// instance of the handler it is.
-LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie, bool IsClangDriver = false);
+LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie,
+ bool IsClangDriver = false);
/// This function registers a function to be called when the user "interrupts"
/// the program (typically by pressing ctrl-c). When the user interrupts the
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 248250cc5ddcb..795e9ab0bcf88 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -73,8 +73,7 @@ using namespace llvm;
using namespace llvm::sys;
InitLLVM::InitLLVM(int &Argc, const char **&Argv,
- bool InstallPipeSignalExitHandler,
- bool IsClangDriver) {
+ bool InstallPipeSignalExitHandler, bool IsClangDriver) {
#ifndef NDEBUG
static std::atomic<bool> Initialized{false};
assert(!Initialized && "InitLLVM was already initialized!");
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 1d1cc9c915a72..ad387bc0f0965 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -505,9 +505,9 @@ void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {
/// Add a function to be called when a signal is delivered to the process. The
/// handler can have a cookie passed to it to identify what instance of the
/// handler it is.
-void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
- void *Cookie, bool IsClangDriver) {
- // Signal-safe.
+void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie,
+ bool IsClangDriver) {
+ // Signal-safe.
insertSignalHandler(FnPtr, Cookie);
RegisterHandlers(IsClangDriver);
}
>From cc01f5a69ba5c4ed3aca7da30fae4fcb5f336460 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Fri, 9 Jan 2026 15:23:09 -0500
Subject: [PATCH 04/10] Use a different AddSignalHandler signature for Windows.
---
llvm/include/llvm/Support/Signals.h | 8 +++++++-
llvm/lib/Support/InitLLVM.cpp | 4 ++++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h
index 9d8fa97eb50b5..7745927dc5258 100644
--- a/llvm/include/llvm/Support/Signals.h
+++ b/llvm/include/llvm/Support/Signals.h
@@ -99,9 +99,15 @@ using SignalHandlerCallback = void (*)(void *);
/// Add a function to be called when an abort/kill signal is delivered to the
/// process. The handler can have a cookie passed to it to identify what
-/// instance of the handler it is.
+/// instance of the handler it is. On Unix systems, the argument IsClangDriver
+/// indicates whether the function is called from a Clang driver so that the
+/// implementation ensures the Clang signal handling complies with POSIX.
+#ifdef _WIN32
+LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie);
+#else
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie,
bool IsClangDriver = false);
+#endif
/// This function registers a function to be called when the user "interrupts"
/// the program (typically by pressing ctrl-c). When the user interrupts the
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 795e9ab0bcf88..2feb0b495d3eb 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -81,7 +81,11 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
#endif
// Bring stdin/stdout/stderr into a known state.
+#ifdef _WIN32
+ sys::AddSignalHandler(CleanupStdHandles, nullptr);
+#else
sys::AddSignalHandler(CleanupStdHandles, nullptr, IsClangDriver);
+#endif
if (InstallPipeSignalExitHandler)
// The pipe signal handler must be installed before any other handlers are
>From c3f220e8842da3ae4af39ab1421667cfa10bfca0 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Fri, 9 Jan 2026 17:19:01 -0500
Subject: [PATCH 05/10] Define and use macro '%crash_opt'. It is '--crash' if
it is not Windows. Otherwise, it is nothing.
---
clang/test/Driver/crash-diagnostics-dir-3.c | 2 +-
clang/test/Driver/crash-diagnostics-dir.c | 2 +-
clang/test/Driver/crash-ir-repro.cpp | 2 +-
clang/test/Driver/crash-report-clang-cl.cpp | 2 +-
clang/test/Driver/crash-report-header.h | 2 +-
clang/test/Driver/crash-report-spaces.c | 2 +-
clang/test/Driver/crash-report-with-asserts.c | 4 ++--
clang/test/Driver/crash-report.cpp | 4 ++--
clang/test/Driver/emit-reproducer.c | 14 +++++++-------
clang/test/Driver/lit.local.cfg | 7 +++++++
clang/test/Driver/output-file-cleanup.c | 2 +-
11 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/clang/test/Driver/crash-diagnostics-dir-3.c b/clang/test/Driver/crash-diagnostics-dir-3.c
index 8d22df85abd2f..63a5efc853a4c 100644
--- a/clang/test/Driver/crash-diagnostics-dir-3.c
+++ b/clang/test/Driver/crash-diagnostics-dir-3.c
@@ -1,6 +1,6 @@
// RUN: export LSAN_OPTIONS=detect_leaks=0
// RUN: rm -rf %t
-// RUN: not --crash env CLANG_CRASH_DIAGNOSTICS_DIR=%t %clang -c %s -o - 2>&1 | FileCheck %s
+// RUN: not %crash_opt env CLANG_CRASH_DIAGNOSTICS_DIR=%t %clang -c %s -o - 2>&1 | FileCheck %s
#pragma clang __debug parser_crash
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir-3.c.tmp{{(/|\\).*}}.c
diff --git a/clang/test/Driver/crash-diagnostics-dir.c b/clang/test/Driver/crash-diagnostics-dir.c
index 56c77beae7234..9a8299bffe005 100644
--- a/clang/test/Driver/crash-diagnostics-dir.c
+++ b/clang/test/Driver/crash-diagnostics-dir.c
@@ -1,6 +1,6 @@
// RUN: export LSAN_OPTIONS=detect_leaks=0
// RUN: rm -rf %t
-// RUN: not --crash %clang -fcrash-diagnostics-dir=%t -c %s -o - 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -fcrash-diagnostics-dir=%t -c %s -o - 2>&1 | FileCheck %s
#pragma clang __debug parser_crash
// CHECK: Preprocessed source(s) and associated run script(s) are located at:
// CHECK: diagnostic msg: {{.*}}{{/|\\}}crash-diagnostics-dir.c.tmp{{(/|\\).*}}.c
diff --git a/clang/test/Driver/crash-ir-repro.cpp b/clang/test/Driver/crash-ir-repro.cpp
index 9d40238e76a23..1a2000ad1279f 100644
--- a/clang/test/Driver/crash-ir-repro.cpp
+++ b/clang/test/Driver/crash-ir-repro.cpp
@@ -1,5 +1,5 @@
// RUN: %clang -S -emit-llvm -o %t.ll %s
-// RUN: not --crash %clang -S -DCRASH %s -o %t.ll 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -S -DCRASH %s -o %t.ll 2>&1 | FileCheck %s
// TODO(boomanaiden154): This test case causes clang to raise a signal when
// running under ubsan, but not in normal build configurations. This should
diff --git a/clang/test/Driver/crash-report-clang-cl.cpp b/clang/test/Driver/crash-report-clang-cl.cpp
index 3efeb8088db52..f61b94626f584 100644
--- a/clang/test/Driver/crash-report-clang-cl.cpp
+++ b/clang/test/Driver/crash-report-clang-cl.cpp
@@ -2,7 +2,7 @@
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: not --crash %clang_cl -fsyntax-only /Brepro /source-charset:utf-8 \
+// RUN: not %crash_opt %clang_cl -fsyntax-only /Brepro /source-charset:utf-8 \
// RUN: -fcrash-diagnostics-dir=%t -- %s 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-clang-cl-*.cpp | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-clang-cl-*.sh | FileCheck --check-prefix=CHECKSH %s
diff --git a/clang/test/Driver/crash-report-header.h b/clang/test/Driver/crash-report-header.h
index 31c71ff625c05..6d5156537126d 100644
--- a/clang/test/Driver/crash-report-header.h
+++ b/clang/test/Driver/crash-report-header.h
@@ -1,7 +1,7 @@
// RUN: export LSAN_OPTIONS=detect_leaks=0
// RUN: rm -rf %t
// RUN: mkdir %t
-// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not --crash %clang -fsyntax-only %s 2>&1 | FileCheck %s
+// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %crash_opt %clang -fsyntax-only %s 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-header-*.h | FileCheck --check-prefix=CHECKSRC "%s"
// RUN: cat %t/crash-report-header-*.sh | FileCheck --check-prefix=CHECKSH "%s"
// REQUIRES: crash-recovery
diff --git a/clang/test/Driver/crash-report-spaces.c b/clang/test/Driver/crash-report-spaces.c
index c01c8df0552de..b5fbb59683fc0 100644
--- a/clang/test/Driver/crash-report-spaces.c
+++ b/clang/test/Driver/crash-report-spaces.c
@@ -2,7 +2,7 @@
// RUN: rm -rf "%t"
// RUN: mkdir "%t"
// RUN: cp "%s" "%t/crash report spaces.c"
-// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not --crash %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s"
+// RUN: env TMPDIR="%t" TEMP="%t" TMP="%t" RC_DEBUG_OPTIONS=1 not %crash_opt %clang -fsyntax-only "%t/crash report spaces.c" 2>&1 | FileCheck "%s"
// RUN: cat "%t/crash report spaces"-*.c | FileCheck --check-prefix=CHECKSRC "%s"
// RUN: cat "%t/crash report spaces"-*.sh | FileCheck --check-prefix=CHECKSH "%s"
// REQUIRES: crash-recovery
diff --git a/clang/test/Driver/crash-report-with-asserts.c b/clang/test/Driver/crash-report-with-asserts.c
index 0b619d9ec2f46..278860a9158e4 100644
--- a/clang/test/Driver/crash-report-with-asserts.c
+++ b/clang/test/Driver/crash-report-with-asserts.c
@@ -12,13 +12,13 @@
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not --crash %clang %s @%t.rsp -DASSERT 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang %s @%t.rsp -DASSERT 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-*.c | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not --crash %clang %s @%t.rsp -DUNREACHABLE 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang %s @%t.rsp -DUNREACHABLE 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-with-asserts-*.c | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-with-asserts-*.sh | FileCheck --check-prefix=CHECKSH %s
diff --git a/clang/test/Driver/crash-report.cpp b/clang/test/Driver/crash-report.cpp
index 4b5adfc02bff4..c431940bf9ea1 100644
--- a/clang/test/Driver/crash-report.cpp
+++ b/clang/test/Driver/crash-report.cpp
@@ -12,13 +12,13 @@
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not --crash %clang %s @%t.rsp -DPARSER 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang %s @%t.rsp -DPARSER 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-*.cpp | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
// RUN: env TMPDIR=%t TEMP=%t TMP=%t RC_DEBUG_OPTIONS=1 \
// RUN: CC_PRINT_HEADERS=1 CC_LOG_DIAGNOSTICS=1 \
-// RUN: not --crash %clang %s @%t.rsp -DCRASH 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang %s @%t.rsp -DCRASH 2>&1 | FileCheck %s
// RUN: cat %t/crash-report-*.cpp | FileCheck --check-prefix=CHECKSRC %s
// RUN: cat %t/crash-report-*.sh | FileCheck --check-prefix=CHECKSH %s
diff --git a/clang/test/Driver/emit-reproducer.c b/clang/test/Driver/emit-reproducer.c
index 28c585193a7d0..6fd1735ee8549 100644
--- a/clang/test/Driver/emit-reproducer.c
+++ b/clang/test/Driver/emit-reproducer.c
@@ -3,13 +3,13 @@
// RUN: echo "%s -fcrash-diagnostics-dir=%t -fsyntax-only" | sed -e 's/\\/\\\\/g' > %t.rsp
-// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT
-// RUN: not --crash %clang -DFATAL @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT
-// RUN: not --crash %clang -DFATAL @%t.rsp 2>&1 | FileCheck %s
-// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=crash 2>&1 | FileCheck %s
-// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=error 2>&1 | FileCheck %s
-// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer=always 2>&1 | FileCheck %s
-// RUN: not --crash %clang -DFATAL @%t.rsp -gen-reproducer 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -DFATAL @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT
+// RUN: not %crash_opt %clang -DFATAL @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT
+// RUN: not %crash_opt %clang -DFATAL @%t.rsp 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -DFATAL @%t.rsp -gen-reproducer=crash 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -DFATAL @%t.rsp -gen-reproducer=error 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -DFATAL @%t.rsp -gen-reproducer=always 2>&1 | FileCheck %s
+// RUN: not %crash_opt %clang -DFATAL @%t.rsp -gen-reproducer 2>&1 | FileCheck %s
// RUN: not %clang -DERROR @%t.rsp -gen-reproducer=off 2>&1 | FileCheck %s --check-prefix=NOT
// RUN: not %clang -DERROR @%t.rsp -fno-crash-diagnostics 2>&1 | FileCheck %s --check-prefix=NOT
diff --git a/clang/test/Driver/lit.local.cfg b/clang/test/Driver/lit.local.cfg
index 6370e9f92d89b..a47d0de90d763 100644
--- a/clang/test/Driver/lit.local.cfg
+++ b/clang/test/Driver/lit.local.cfg
@@ -1,4 +1,5 @@
from lit.llvm import llvm_config
+import sys
config.suffixes = [
".c",
@@ -27,6 +28,12 @@ config.substitutions.insert(
0, ("%clang_cc1", """*** Do not use 'clang -cc1' in Driver tests. ***""")
)
+is_windows = sys.platform.startswith("win")
+if is_windows:
+ config.substitutions.append(('%crash_opt', ''))
+else:
+ config.substitutions.append(('%crash_opt', '--crash'))
+
# Remove harmful environmental variables for clang Driver tests.
# Some might be useful for other tests so they are only removed here.
driver_overwrite_env_vars = [
diff --git a/clang/test/Driver/output-file-cleanup.c b/clang/test/Driver/output-file-cleanup.c
index b5f548dc0b01a..432ff640656e7 100644
--- a/clang/test/Driver/output-file-cleanup.c
+++ b/clang/test/Driver/output-file-cleanup.c
@@ -2,7 +2,7 @@
// RUN: rm -f "%t.d" "%t1.s" "%t2.s" "%t3.s" "%t4.s" "%t5.s"
//
// RUN: touch %t.s
-// RUN: not --crash %clang -S -DCRASH -o %t.s -MMD -MF %t.d %s
+// RUN: not %crash_opt %clang -S -DCRASH -o %t.s -MMD -MF %t.d %s
// RUN: test ! -f %t.s
// RUN: test ! -f %t.d
>From 8b132975ae34413760d8a49b42ee256c629ef537 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 2 Feb 2026 12:50:24 -0500
Subject: [PATCH 06/10] Addressed comment: - rename IsClangDriver to
NeedsPOSIXUtilitySignalHandling
---
llvm/cmake/modules/AddLLVM.cmake | 2 +-
llvm/include/llvm/Support/InitLLVM.h | 4 ++--
llvm/include/llvm/Support/Signals.h | 9 +++++----
llvm/lib/Support/InitLLVM.cpp | 4 ++--
llvm/lib/Support/Unix/Signals.inc | 12 ++++++------
5 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index b4ca46a874067..81aaf6034cca7 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -1008,7 +1008,7 @@ macro(generate_llvm_objects name)
set(INITLLVM_ARGS "")
if(${name} STREQUAL "clang")
- set(INITLLVM_ARGS ", /*InstallPipeSignalExitHandler=*/true, /*IsClangDriver=*/true")
+ set(INITLLVM_ARGS ", /*InstallPipeSignalExitHandler=*/true, /*NeedsPOSIXUtilitySignalHandling=*/true")
endif()
foreach(path ${CMAKE_MODULE_PATH})
diff --git a/llvm/include/llvm/Support/InitLLVM.h b/llvm/include/llvm/Support/InitLLVM.h
index 6859964bd8f22..616e1baf6ad76 100644
--- a/llvm/include/llvm/Support/InitLLVM.h
+++ b/llvm/include/llvm/Support/InitLLVM.h
@@ -39,9 +39,9 @@ class InitLLVM {
bool InstallPipeSignalExitHandler = true,
bool IsClandDriver = false);
InitLLVM(int &Argc, char **&Argv, bool InstallPipeSignalExitHandler = true,
- bool IsClangDriver = false)
+ bool NeedsPOSIXUtilitySignalHandling = false)
: InitLLVM(Argc, const_cast<const char **&>(Argv),
- InstallPipeSignalExitHandler, IsClangDriver) {}
+ InstallPipeSignalExitHandler, NeedsPOSIXUtilitySignalHandling) {}
LLVM_ABI ~InitLLVM();
diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h
index 7745927dc5258..916d0ed7dea69 100644
--- a/llvm/include/llvm/Support/Signals.h
+++ b/llvm/include/llvm/Support/Signals.h
@@ -99,14 +99,15 @@ using SignalHandlerCallback = void (*)(void *);
/// Add a function to be called when an abort/kill signal is delivered to the
/// process. The handler can have a cookie passed to it to identify what
-/// instance of the handler it is. On Unix systems, the argument IsClangDriver
-/// indicates whether the function is called from a Clang driver so that the
-/// implementation ensures the Clang signal handling complies with POSIX.
+/// instance of the handler it is. On Unix systems, the
+/// NeedsPOSIXUtilitySignalHandling argument indicates whether POSIX signal
+/// handling semantics are followed, so that the signal handler resignals
+/// itself to terminate after handling the signal.
#ifdef _WIN32
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie);
#else
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie,
- bool IsClangDriver = false);
+ bool NeedsPOSIXUtilitySignalHandling = false);
#endif
/// This function registers a function to be called when the user "interrupts"
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 2feb0b495d3eb..d214daf437e27 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -73,7 +73,7 @@ using namespace llvm;
using namespace llvm::sys;
InitLLVM::InitLLVM(int &Argc, const char **&Argv,
- bool InstallPipeSignalExitHandler, bool IsClangDriver) {
+ bool InstallPipeSignalExitHandler, bool NeedsPOSIXUtilitySignalHandling) {
#ifndef NDEBUG
static std::atomic<bool> Initialized{false};
assert(!Initialized && "InitLLVM was already initialized!");
@@ -84,7 +84,7 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
#ifdef _WIN32
sys::AddSignalHandler(CleanupStdHandles, nullptr);
#else
- sys::AddSignalHandler(CleanupStdHandles, nullptr, IsClangDriver);
+ sys::AddSignalHandler(CleanupStdHandles, nullptr, NeedsPOSIXUtilitySignalHandling);
#endif
if (InstallPipeSignalExitHandler)
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index ad387bc0f0965..dffbe2146aaa5 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -293,7 +293,7 @@ static void CreateSigAltStack() {
static void CreateSigAltStack() {}
#endif
-static void RegisterHandlers(bool IsClangDriver = false) { // Not signal-safe.
+static void RegisterHandlers(bool NeedsPOSIXUtilitySignalHandling = false) { // Not signal-safe.
// The mutex prevents other threads from registering handlers while we're
// doing it. We also have to protect the handlers and their count because
// a signal handler could fire while we're registering handlers.
@@ -322,9 +322,9 @@ static void RegisterHandlers(bool IsClangDriver = false) { // Not signal-safe.
NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK | SA_SIGINFO;
break;
case SignalKind::IsInfo:
- if (IsClangDriver)
- // If it is the Clang driver the signal handler resignal itself to
- // terminate after handling the signal.
+ if (NeedsPOSIXUtilitySignalHandling)
+ // If POSIX signal-handling semantics are followed, the signal handler
+ // resignal itself to terminate after handling the signal.
NewHandler.sa_handler = InfoSignalHandlerTerminate;
else
NewHandler.sa_handler = InfoSignalHandler;
@@ -506,10 +506,10 @@ void llvm::sys::DontRemoveFileOnSignal(StringRef Filename) {
/// handler can have a cookie passed to it to identify what instance of the
/// handler it is.
void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie,
- bool IsClangDriver) {
+ bool NeedsPOSIXUtilitySignalHandling) {
// Signal-safe.
insertSignalHandler(FnPtr, Cookie);
- RegisterHandlers(IsClangDriver);
+ RegisterHandlers(NeedsPOSIXUtilitySignalHandling);
}
#if ENABLE_BACKTRACES && defined(HAVE_BACKTRACE) && \
>From 4ecbc5ba964bde2247b619935bfd44eaa9a8f87f Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 2 Feb 2026 13:01:58 -0500
Subject: [PATCH 07/10] Fix formatting.
---
llvm/include/llvm/Support/InitLLVM.h | 3 ++-
llvm/lib/Support/InitLLVM.cpp | 6 ++++--
llvm/lib/Support/Unix/Signals.inc | 3 ++-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/Support/InitLLVM.h b/llvm/include/llvm/Support/InitLLVM.h
index 616e1baf6ad76..02a315790e139 100644
--- a/llvm/include/llvm/Support/InitLLVM.h
+++ b/llvm/include/llvm/Support/InitLLVM.h
@@ -41,7 +41,8 @@ class InitLLVM {
InitLLVM(int &Argc, char **&Argv, bool InstallPipeSignalExitHandler = true,
bool NeedsPOSIXUtilitySignalHandling = false)
: InitLLVM(Argc, const_cast<const char **&>(Argv),
- InstallPipeSignalExitHandler, NeedsPOSIXUtilitySignalHandling) {}
+ InstallPipeSignalExitHandler,
+ NeedsPOSIXUtilitySignalHandling) {}
LLVM_ABI ~InitLLVM();
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index d214daf437e27..797c5d35bec35 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -73,7 +73,8 @@ using namespace llvm;
using namespace llvm::sys;
InitLLVM::InitLLVM(int &Argc, const char **&Argv,
- bool InstallPipeSignalExitHandler, bool NeedsPOSIXUtilitySignalHandling) {
+ bool InstallPipeSignalExitHandler,
+ bool NeedsPOSIXUtilitySignalHandling) {
#ifndef NDEBUG
static std::atomic<bool> Initialized{false};
assert(!Initialized && "InitLLVM was already initialized!");
@@ -84,7 +85,8 @@ InitLLVM::InitLLVM(int &Argc, const char **&Argv,
#ifdef _WIN32
sys::AddSignalHandler(CleanupStdHandles, nullptr);
#else
- sys::AddSignalHandler(CleanupStdHandles, nullptr, NeedsPOSIXUtilitySignalHandling);
+ sys::AddSignalHandler(CleanupStdHandles, nullptr,
+ NeedsPOSIXUtilitySignalHandling);
#endif
if (InstallPipeSignalExitHandler)
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index dffbe2146aaa5..d7f1368428694 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -293,7 +293,8 @@ static void CreateSigAltStack() {
static void CreateSigAltStack() {}
#endif
-static void RegisterHandlers(bool NeedsPOSIXUtilitySignalHandling = false) { // Not signal-safe.
+static void RegisterHandlers(
+ bool NeedsPOSIXUtilitySignalHandling = false) { // Not signal-safe.
// The mutex prevents other threads from registering handlers while we're
// doing it. We also have to protect the handlers and their count because
// a signal handler could fire while we're registering handlers.
>From 1ccd5fe4ea28621d847c4236d1d3143d45539b76 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 9 Feb 2026 11:07:54 -0500
Subject: [PATCH 08/10] Address comments: * correct the argument name of
InitLLVM() * make the signature of AddSignalHandler() the same for all
platforms * guard behavior changes with NeedsPOSIXUtilitySignalHandling
---
clang/tools/driver/driver.cpp | 2 +-
.../llvm/Support/CrashRecoveryContext.h | 2 +-
llvm/include/llvm/Support/InitLLVM.h | 2 +-
llvm/include/llvm/Support/Signals.h | 12 ++----
llvm/lib/Support/CrashRecoveryContext.cpp | 25 +++++++-----
llvm/lib/Support/Unix/Signals.inc | 40 ++++++++++++-------
llvm/lib/Support/Windows/Signals.inc | 3 +-
7 files changed, 48 insertions(+), 38 deletions(-)
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index a586494cdc8a9..e6cabcc7eb530 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -381,7 +381,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
if (!UseNewCC1Process) {
TheDriver.CC1Main = ExecuteCC1WithContext;
// Ensure the CC1Command actually catches cc1 crashes
- llvm::CrashRecoveryContext::Enable();
+ llvm::CrashRecoveryContext::Enable(true);
}
std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args));
diff --git a/llvm/include/llvm/Support/CrashRecoveryContext.h b/llvm/include/llvm/Support/CrashRecoveryContext.h
index ffee81dd24587..4abd2d0eedcde 100644
--- a/llvm/include/llvm/Support/CrashRecoveryContext.h
+++ b/llvm/include/llvm/Support/CrashRecoveryContext.h
@@ -60,7 +60,7 @@ class CrashRecoveryContext {
LLVM_ABI void unregisterCleanup(CrashRecoveryContextCleanup *cleanup);
/// Enable crash recovery.
- LLVM_ABI static void Enable();
+ LLVM_ABI static void Enable(bool NeedsPOSIXUtilitySignalHandling = false);
/// Disable crash recovery.
LLVM_ABI static void Disable();
diff --git a/llvm/include/llvm/Support/InitLLVM.h b/llvm/include/llvm/Support/InitLLVM.h
index 02a315790e139..4d513bfd576bb 100644
--- a/llvm/include/llvm/Support/InitLLVM.h
+++ b/llvm/include/llvm/Support/InitLLVM.h
@@ -37,7 +37,7 @@ class InitLLVM {
public:
LLVM_ABI InitLLVM(int &Argc, const char **&Argv,
bool InstallPipeSignalExitHandler = true,
- bool IsClandDriver = false);
+ bool NeedsPOSIXUtilitySignalHandling = false);
InitLLVM(int &Argc, char **&Argv, bool InstallPipeSignalExitHandler = true,
bool NeedsPOSIXUtilitySignalHandling = false)
: InitLLVM(Argc, const_cast<const char **&>(Argv),
diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h
index 916d0ed7dea69..d9bff20b85393 100644
--- a/llvm/include/llvm/Support/Signals.h
+++ b/llvm/include/llvm/Support/Signals.h
@@ -99,16 +99,12 @@ using SignalHandlerCallback = void (*)(void *);
/// Add a function to be called when an abort/kill signal is delivered to the
/// process. The handler can have a cookie passed to it to identify what
-/// instance of the handler it is. On Unix systems, the
-/// NeedsPOSIXUtilitySignalHandling argument indicates whether POSIX signal
-/// handling semantics are followed, so that the signal handler resignals
-/// itself to terminate after handling the signal.
-#ifdef _WIN32
-LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie);
-#else
+/// instance of the handler it is. The NeedsPOSIXUtilitySignalHandling
+/// argument indicates whether POSIX signal handling semantics are followed,
+/// so that the signal handler resignals itself to terminate after handling
+/// the signal.
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie,
bool NeedsPOSIXUtilitySignalHandling = false);
-#endif
/// This function registers a function to be called when the user "interrupts"
/// the program (typically by pressing ctrl-c). When the user interrupts the
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index c6bfa4d0245da..d8318ba6caa35 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -92,7 +92,7 @@ static LLVM_THREAD_LOCAL const CrashRecoveryContext *IsRecoveringFromCrash;
} // namespace
-static void installExceptionOrSignalHandlers();
+static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling);
static void uninstallExceptionOrSignalHandlers();
CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() = default;
@@ -137,13 +137,13 @@ CrashRecoveryContext *CrashRecoveryContext::GetCurrent() {
return CRCI->CRC;
}
-void CrashRecoveryContext::Enable() {
+void CrashRecoveryContext::Enable(bool NeedsPOSIXUtilitySignalHandling) {
std::lock_guard<std::mutex> L(getCrashRecoveryContextMutex());
// FIXME: Shouldn't this be a refcount or something?
if (gCrashRecoveryEnabled)
return;
gCrashRecoveryEnabled = true;
- installExceptionOrSignalHandlers();
+ installExceptionOrSignalHandlers(NeedsPOSIXUtilitySignalHandling);
}
void CrashRecoveryContext::Disable() {
@@ -193,7 +193,7 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
// catches exceptions if they would bubble out from the stack frame with __try /
// __except.
-static void installExceptionOrSignalHandlers() {}
+static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {}
static void uninstallExceptionOrSignalHandlers() {}
// We need this function because the call to GetExceptionInformation() can only
@@ -309,7 +309,7 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
// non-NULL, valid VEH handles, or NULL.
static LLVM_THREAD_LOCAL const void* sCurrentExceptionHandle;
-static void installExceptionOrSignalHandlers() {
+static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {
// We can set up vectored exception handling now. We will install our
// handler as the front of the list, though there's no assurances that
// it will remain at the front (another call could install itself before
@@ -390,7 +390,7 @@ static void CrashRecoverySignalHandler(int Signal) {
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(RetCode, Signal);
}
-static void installExceptionOrSignalHandlers() {
+static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {
// Setup the signal handler.
struct sigaction Handler;
Handler.sa_handler = CrashRecoverySignalHandler;
@@ -398,11 +398,14 @@ static void installExceptionOrSignalHandlers() {
sigemptyset(&Handler.sa_mask);
for (unsigned i = 0; i != NumSignals; ++i) {
- struct sigaction act;
- sigaction(Signals[i], NULL, &act);
- // Don't install signal handler if the disposition of a signal is SIG_IGN.
- if (act.sa_handler != SIG_IGN)
- sigaction(Signals[i], &Handler, &PrevActions[i]);
+ if (NeedsPOSIXUtilitySignalHandling) {
+ // Don't install the new handler if the signal disposition is SIG_IGN.
+ struct sigaction act;
+ if (sigaction(Signals[i], NULL, &act) == 0 && act.sa_handler != SIG_IGN)
+ sigaction(Signals[i], &Handler, &PrevActions[i]);
+ } else {
+ sigaction(Signals[i], &Handler, &PrevActions[i]);
+ }
}
}
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index d7f1368428694..9de01ab6cf539 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -84,7 +84,8 @@
using namespace llvm;
-static void SignalHandler(int Sig, siginfo_t *Info, void *);
+static void SignalHandler(int Sig, siginfo_t *Info, void *Context);
+static void SignalHandlerTerminate(int Sig, siginfo_t *Info, void *Context);
static void InfoSignalHandler(int Sig); // defined below.
static void InfoSignalHandlerTerminate(int Sig); // defined below.
@@ -319,7 +320,12 @@ static void RegisterHandlers(
switch (Kind) {
case SignalKind::IsKill:
- NewHandler.sa_sigaction = SignalHandler;
+ if (NeedsPOSIXUtilitySignalHandling)
+ // If POSIX signal-handling semantics are followed, the signal handler
+ // resignal itself to terminate after handling the signal.
+ NewHandler.sa_sigaction = SignalHandlerTerminate;
+ else
+ NewHandler.sa_sigaction = SignalHandler;
NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK | SA_SIGINFO;
break;
case SignalKind::IsInfo:
@@ -334,12 +340,14 @@ static void RegisterHandlers(
}
sigemptyset(&NewHandler.sa_mask);
- // Install the new handler if the signal disposition isn't SIG_IGN,
- // save the old one in RegisteredSignalInfo.
- struct sigaction act;
- sigaction(Signal, NULL, &act);
- if (act.sa_handler != SIG_IGN)
+ if (NeedsPOSIXUtilitySignalHandling) {
+ // Don't install the new handler if the signal disposition is SIG_IGN.
+ struct sigaction act;
+ if (sigaction(Signal, NULL, &act) == 0 && act.sa_handler != SIG_IGN)
+ sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
+ } else {
sigaction(Signal, &NewHandler, &RegisteredSignalInfo[Index].SA);
+ }
RegisteredSignalInfo[Index].SigNo = Signal;
++NumRegisteredSignals;
};
@@ -388,7 +396,7 @@ void sys::CleanupOnSignal(uintptr_t Context) {
}
// The signal handler that runs.
-static void SignalHandler(int Sig, siginfo_t *Info, void *) {
+static void SignalHandler(int Sig, siginfo_t *Info, void *Context) {
// Restore the signal behavior to default, so that the program actually
// crashes when we return and the signal reissues. This also ensures that if
// we crash in our signal handler that the program will terminate immediately
@@ -422,13 +430,6 @@ static void SignalHandler(int Sig, siginfo_t *Info, void *) {
// Otherwise if it is a fault (like SEGV) run any handler.
llvm::sys::RunSignalHandlers();
- // Resignal if it is a kill signal so that the exit code contains the
- // terminating signal number.
- if (llvm::is_contained(KillSigs, Sig)) {
- raise(Sig); // Execute the default handler.
- return;
- }
-
#if defined(__linux__)
// Re-raising a signal via `raise` loses the original siginfo. Recent
// versions of linux (>= 3.9) support processes sending a signal to itself
@@ -446,6 +447,15 @@ static void SignalHandler(int Sig, siginfo_t *Info, void *) {
#endif
}
+static void SignalHandlerTerminate(int Sig, siginfo_t *Info, void *Context) {
+ SignalHandler(Sig, Info, Context);
+
+ // Resignal if it is a kill signal so that the exit code contains the
+ // terminating signal number.
+ if (llvm::is_contained(KillSigs, Sig))
+ raise(Sig); // Execute the default handler.
+}
+
static void InfoSignalHandler(int Sig) {
SaveAndRestore SaveErrnoDuringASignalHandler(errno);
if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction)
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index eec112e5a80f5..d73ad6cda6ddc 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -550,7 +550,8 @@ void llvm::sys::CallOneShotPipeSignalHandler() {
/// handler can have a cookie passed to it to identify what instance of the
/// handler it is.
void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
- void *Cookie) {
+ void *Cookie,
+ bool NeedsPOSIXUtilitySignalHandling)
insertSignalHandler(FnPtr, Cookie);
RegisterHandler();
LeaveCriticalSection(&CriticalSection);
>From 4d4bf564d097e986f79bc41de81244c18fe09baf Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 9 Feb 2026 11:39:08 -0500
Subject: [PATCH 09/10] Fix formatting.
---
llvm/lib/Support/CrashRecoveryContext.cpp | 14 +++++++++-----
llvm/lib/Support/Windows/Signals.inc | 3 +--
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index d8318ba6caa35..cf35fdd9f3aa6 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -92,7 +92,8 @@ static LLVM_THREAD_LOCAL const CrashRecoveryContext *IsRecoveringFromCrash;
} // namespace
-static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling);
+static void
+installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling);
static void uninstallExceptionOrSignalHandlers();
CrashRecoveryContextCleanup::~CrashRecoveryContextCleanup() = default;
@@ -193,7 +194,8 @@ CrashRecoveryContext::unregisterCleanup(CrashRecoveryContextCleanup *cleanup) {
// catches exceptions if they would bubble out from the stack frame with __try /
// __except.
-static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {}
+static void
+installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {}
static void uninstallExceptionOrSignalHandlers() {}
// We need this function because the call to GetExceptionInformation() can only
@@ -309,7 +311,8 @@ static LONG CALLBACK ExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
// non-NULL, valid VEH handles, or NULL.
static LLVM_THREAD_LOCAL const void* sCurrentExceptionHandle;
-static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {
+static void
+installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {
// We can set up vectored exception handling now. We will install our
// handler as the front of the list, though there's no assurances that
// it will remain at the front (another call could install itself before
@@ -390,7 +393,8 @@ static void CrashRecoverySignalHandler(int Signal) {
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(RetCode, Signal);
}
-static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {
+static void
+installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandling) {
// Setup the signal handler.
struct sigaction Handler;
Handler.sa_handler = CrashRecoverySignalHandler;
@@ -404,7 +408,7 @@ static void installExceptionOrSignalHandlers(bool NeedsPOSIXUtilitySignalHandlin
if (sigaction(Signals[i], NULL, &act) == 0 && act.sa_handler != SIG_IGN)
sigaction(Signals[i], &Handler, &PrevActions[i]);
} else {
- sigaction(Signals[i], &Handler, &PrevActions[i]);
+ sigaction(Signals[i], &Handler, &PrevActions[i]);
}
}
}
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index d73ad6cda6ddc..4be5a07fe23ce 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -549,8 +549,7 @@ void llvm::sys::CallOneShotPipeSignalHandler() {
/// Add a function to be called when a signal is delivered to the process. The
/// handler can have a cookie passed to it to identify what instance of the
/// handler it is.
-void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr,
- void *Cookie,
+void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie,
bool NeedsPOSIXUtilitySignalHandling)
insertSignalHandler(FnPtr, Cookie);
RegisterHandler();
>From 90ec9a5c6ea91f41c2cca7becccf151d16ca71a8 Mon Sep 17 00:00:00 2001
From: Xing Xue <xingxue at outlook.com>
Date: Mon, 9 Feb 2026 12:50:59 -0500
Subject: [PATCH 10/10] Fix formatting (don't understand it though).
---
llvm/lib/Support/Windows/Signals.inc | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index 4be5a07fe23ce..a93d3abf6f50d 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -551,9 +551,9 @@ void llvm::sys::CallOneShotPipeSignalHandler() {
/// handler it is.
void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie,
bool NeedsPOSIXUtilitySignalHandling)
- insertSignalHandler(FnPtr, Cookie);
- RegisterHandler();
- LeaveCriticalSection(&CriticalSection);
+ insertSignalHandler(FnPtr, Cookie);
+RegisterHandler();
+LeaveCriticalSection(&CriticalSection);
}
static void Cleanup(bool ExecuteSignalHandlers) {
More information about the llvm-commits
mailing list