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/2] 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/2] 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) && \ _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
