https://github.com/xingxue-ibm updated 
https://github.com/llvm/llvm-project/pull/169340

>From b9937432c640f3b9755bdc8927bddf4e10b7a8b9 Mon Sep 17 00:00:00 2001
From: Xing Xue <[email protected]>
Date: Fri, 21 Nov 2025 15:29:56 -0500
Subject: [PATCH 1/4] 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 eb3f9cbea2845..9ca0bb8cac420 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2300,7 +2300,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 1a4bdebddf0b19d8dd9467d7afab4faf02086e9c Mon Sep 17 00:00:00 2001
From: Xing Xue <[email protected]>
Date: Fri, 9 Jan 2026 12:41:58 -0500
Subject: [PATCH 2/4] 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 fd97e6f0cce11..16faabe84d29e 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
 
 // CHECK: Preprocessed source(s) and associated run script(s) are located at:
 // CHECK-NEXT: clang: note: diagnostic msg: {{.*}}.cpp
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 d6acb4f984be9..921d90a455078 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -989,6 +989,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@_main(int argc, char **, const llvm::ToolContext &);
 
 int main(int argc, char **argv) {
-  llvm::InitLLVM X(argc, argv);
+  llvm::InitLLVM X(argc, argv@INITLLVM_ARGS@);
   return @TOOL_NAME@_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 81d76ffdcafd2358cab474c0760c5254ffe32956 Mon Sep 17 00:00:00 2001
From: Xing Xue <[email protected]>
Date: Fri, 9 Jan 2026 12:52:48 -0500
Subject: [PATCH 3/4] 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 0ab850be4f8ea408751a69ca62ea8f565729aece Mon Sep 17 00:00:00 2001
From: Xing Xue <[email protected]>
Date: Fri, 9 Jan 2026 15:23:09 -0500
Subject: [PATCH 4/4] 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

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to