diff options
author | Vedant Kumar <vsk@apple.com> | 2021-01-08 11:08:52 -0800 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2021-01-08 15:13:04 -0800 |
commit | e05baf40de8a3bbfcf4a765761b1147e94b7309c (patch) | |
tree | ee78b49ebaad0c1c1add313860d31dd4ee3bef5d | |
parent | d86e16e4bd5ed90f08e6e787785b485636a2184d (diff) | |
download | llvm-e05baf40de8a3bbfcf4a765761b1147e94b7309c.zip llvm-e05baf40de8a3bbfcf4a765761b1147e94b7309c.tar.gz llvm-e05baf40de8a3bbfcf4a765761b1147e94b7309c.tar.bz2 |
[InitLLVM] Ensure SIGPIPE handler installed before sigaction()
The pipe signal handler must be installed before any other handlers are
registered. This is because the Unix RegisterHandlers function does not
perform a sigaction() for SIGPIPE unless a one-shot handler is present,
to allow long-lived processes (like lldb) to fully opt-out of llvm's
SIGPIPE handling and ignore the signal safely.
Fixes a bug introduced in D70277.
Tested by running Nick's test case:
% xcrun ./bin/clang -E -fno-integrated-cc1 x.c | tee foo.txt | head
I verified that child cc1 process exits with IO_ERR, and that the parent
recognizes the error code, exiting cleanly.
Differential Revision: https://reviews.llvm.org/D94324
-rw-r--r-- | clang/test/Driver/sigpipe-handling.c | 9 | ||||
-rw-r--r-- | llvm/include/llvm/Support/InitLLVM.h | 3 | ||||
-rw-r--r-- | llvm/lib/Support/InitLLVM.cpp | 11 |
3 files changed, 20 insertions, 3 deletions
diff --git a/clang/test/Driver/sigpipe-handling.c b/clang/test/Driver/sigpipe-handling.c new file mode 100644 index 0000000..852f0bf --- /dev/null +++ b/clang/test/Driver/sigpipe-handling.c @@ -0,0 +1,9 @@ +// REQUIRES: shell +// RUN: %clang -E -fno-integrated-cc1 %s | head | FileCheck %s + +// Test that the parent clang driver process doesn't crash when the child cc1 +// process receives a SIGPIPE (Unix-only). +// +// The child should exit with IO_ERR, and the parent should exit cleanly. + +// CHECK: sigpipe-handling.c diff --git a/llvm/include/llvm/Support/InitLLVM.h b/llvm/include/llvm/Support/InitLLVM.h index 3be8d6b..879dc15 100644 --- a/llvm/include/llvm/Support/InitLLVM.h +++ b/llvm/include/llvm/Support/InitLLVM.h @@ -9,6 +9,7 @@ #ifndef LLVM_SUPPORT_LLVM_H #define LLVM_SUPPORT_LLVM_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/PrettyStackTrace.h" @@ -44,7 +45,7 @@ public: private: BumpPtrAllocator Alloc; SmallVector<const char *, 0> Args; - PrettyStackTraceProgram StackPrinter; + Optional<PrettyStackTraceProgram> StackPrinter; }; } // namespace llvm diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp index 5c56b77..152de6e 100644 --- a/llvm/lib/Support/InitLLVM.cpp +++ b/llvm/lib/Support/InitLLVM.cpp @@ -22,10 +22,17 @@ using namespace llvm; using namespace llvm::sys; InitLLVM::InitLLVM(int &Argc, const char **&Argv, - bool InstallPipeSignalExitHandler) - : StackPrinter(Argc, Argv) { + bool InstallPipeSignalExitHandler) { if (InstallPipeSignalExitHandler) + // The pipe signal handler must be installed before any other handlers are + // registered. This is because the Unix \ref RegisterHandlers function does + // not perform a sigaction() for SIGPIPE unless a one-shot handler is + // present, to allow long-lived processes (like lldb) to fully opt-out of + // llvm's SIGPIPE handling and ignore the signal safely. sys::SetOneShotPipeSignalFunction(sys::DefaultOneShotPipeSignalHandler); + // Initialize the stack printer after installing the one-shot pipe signal + // handler, so we can perform a sigaction() for SIGPIPE on Unix if requested. + StackPrinter.emplace(Argc, Argv); sys::PrintStackTraceOnErrorSignal(Argv[0]); install_out_of_memory_new_handler(); |