summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support
diff options
context:
space:
mode:
authorVedant Kumar <vsk@apple.com>2019-11-14 14:30:56 -0800
committerVedant Kumar <vsk@apple.com>2019-11-18 10:27:27 -0800
commit4624e83ce7b124545b55e45ba13f2d900ed65654 (patch)
tree740c1cb7f4666d5cd5f1895184e0a3d4699f1004 /llvm/lib/Support
parent5a4a05d776d3adacad344b2b5e15cf594c906bce (diff)
downloadbcm5719-llvm-4624e83ce7b124545b55e45ba13f2d900ed65654.tar.gz
bcm5719-llvm-4624e83ce7b124545b55e45ba13f2d900ed65654.zip
[Signal] Allow llvm clients to opt into one-shot SIGPIPE handling
Allow clients of the llvm library to opt-in to one-shot SIGPIPE handling, instead of forcing them to undo llvm's SIGPIPE handler registration (which is brittle). The current behavior is preserved for all llvm-derived tools (except lldb) by means of a default-`true` flag in the InitLLVM constructor. This prevents "IO error" crashes in long-lived processes (lldb is the motivating example) which both a) load llvm as a dynamic library and b) *really* need to ignore SIGPIPE. As llvm signal handlers can be installed when calling into libclang (say, via RemoveFileOnSignal), thereby overriding a previous SIG_IGN for SIGPIPE, there is no clean way to opt-out of "exit-on-SIGPIPE" in the current model. Differential Revision: https://reviews.llvm.org/D70277
Diffstat (limited to 'llvm/lib/Support')
-rw-r--r--llvm/lib/Support/InitLLVM.cpp6
-rw-r--r--llvm/lib/Support/Unix/Signals.inc24
-rw-r--r--llvm/lib/Support/Windows/Signals.inc7
3 files changed, 32 insertions, 5 deletions
diff --git a/llvm/lib/Support/InitLLVM.cpp b/llvm/lib/Support/InitLLVM.cpp
index 0d7d7fcc8cb..bb9b569d2de 100644
--- a/llvm/lib/Support/InitLLVM.cpp
+++ b/llvm/lib/Support/InitLLVM.cpp
@@ -21,7 +21,11 @@
using namespace llvm;
using namespace llvm::sys;
-InitLLVM::InitLLVM(int &Argc, const char **&Argv) : StackPrinter(Argc, Argv) {
+InitLLVM::InitLLVM(int &Argc, const char **&Argv,
+ bool InstallPipeSignalExitHandler)
+ : StackPrinter(Argc, Argv) {
+ if (InstallPipeSignalExitHandler)
+ sys::SetOneShotPipeSignalFunction(sys::DefaultOneShotPipeSignalHandler);
sys::PrintStackTraceOnErrorSignal(Argv[0]);
install_out_of_memory_new_handler();
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index be05eabfb2e..8c26fa9b8f2 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -88,6 +88,9 @@ static std::atomic<SignalHandlerFunctionType> InterruptFunction =
ATOMIC_VAR_INIT(nullptr);
static std::atomic<SignalHandlerFunctionType> InfoSignalFunction =
ATOMIC_VAR_INIT(nullptr);
+/// The function to call on SIGPIPE (one-time use only).
+static std::atomic<SignalHandlerFunctionType> OneShotPipeSignalFunction =
+ ATOMIC_VAR_INIT(nullptr);
namespace {
/// Signal-safe removal of files.
@@ -206,7 +209,7 @@ static StringRef Argv0;
/// if there is, it's not our direct responsibility. For whatever reason, our
/// continued execution is no longer desirable.
static const int IntSigs[] = {
- SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR2
+ SIGHUP, SIGINT, SIGTERM, SIGUSR2
};
/// Signals that represent that we have a bug, and our prompt termination has
@@ -237,7 +240,7 @@ static const int InfoSigs[] = {
static const size_t NumSigs =
array_lengthof(IntSigs) + array_lengthof(KillSigs) +
- array_lengthof(InfoSigs);
+ array_lengthof(InfoSigs) + 1 /* SIGPIPE */;
static std::atomic<unsigned> NumRegisteredSignals = ATOMIC_VAR_INIT(0);
@@ -322,6 +325,8 @@ static void RegisterHandlers() { // Not signal-safe.
registerHandler(S, SignalKind::IsKill);
for (auto S : KillSigs)
registerHandler(S, SignalKind::IsKill);
+ if (OneShotPipeSignalFunction)
+ registerHandler(SIGPIPE, SignalKind::IsKill);
for (auto S : InfoSigs)
registerHandler(S, SignalKind::IsInfo);
}
@@ -361,9 +366,10 @@ static RETSIGTYPE SignalHandler(int Sig) {
if (auto OldInterruptFunction = InterruptFunction.exchange(nullptr))
return OldInterruptFunction();
- // Send a special return code that drivers can check for, from sysexits.h.
if (Sig == SIGPIPE)
- exit(EX_IOERR);
+ if (auto OldOneShotPipeFunction =
+ OneShotPipeSignalFunction.exchange(nullptr))
+ return OldOneShotPipeFunction();
raise(Sig); // Execute the default handler.
return;
@@ -403,6 +409,16 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
RegisterHandlers();
}
+void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
+ OneShotPipeSignalFunction.exchange(Handler);
+ RegisterHandlers();
+}
+
+void llvm::sys::DefaultOneShotPipeSignalHandler() {
+ // Send a special return code that drivers can check for, from sysexits.h.
+ exit(EX_IOERR);
+}
+
// The public API
bool llvm::sys::RemoveFileOnSignal(StringRef Filename,
std::string* ErrMsg) {
diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc
index 6a820ef22b1..08a3616427b 100644
--- a/llvm/lib/Support/Windows/Signals.inc
+++ b/llvm/lib/Support/Windows/Signals.inc
@@ -560,6 +560,13 @@ void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
// Unimplemented.
}
+void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
+ // Unimplemented.
+}
+
+void llvm::sys::DefaultOneShotPipeSignalHandler() {
+ // Unimplemented.
+}
/// 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
OpenPOWER on IntegriCloud