summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support/Unix/Signals.inc
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2019-07-12 16:05:09 +0000
committerJordan Rose <jordan_rose@apple.com>2019-07-12 16:05:09 +0000
commitbe28cddeeaa6e4377de9365e506645ee1eb97e35 (patch)
treef827146dfe75e117c032ac5493ff8c5c778922a8 /llvm/lib/Support/Unix/Signals.inc
parent27ec195f391cf1bcf39fe25f345bc63061566c3c (diff)
downloadbcm5719-llvm-be28cddeeaa6e4377de9365e506645ee1eb97e35.tar.gz
bcm5719-llvm-be28cddeeaa6e4377de9365e506645ee1eb97e35.zip
Support for dumping current PrettyStackTrace on SIGINFO (Ctrl-T)
Support SIGINFO (and SIGUSR1 for POSIX purposes) to tell what long-running jobs are doing, as inspired by BSD tools (including on macOS), by dumping the current PrettyStackTrace. This adds a new kind of signal handler for non-fatal "info" signals, similar to the "interrupt" handler that already exists for SIGINT (Ctrl-C). It then uses that handler to update a "generation count" managed by the PrettyStackTrace infrastructure, which is then checked whenever a PrettyStackTraceEntry is pushed or popped on each thread. If the generation has changed---i.e. if the user has pressed Ctrl-T---the stack trace is dumped, though unfortunately it can't include the deepest entry because that one is currently being constructed/destructed. https://reviews.llvm.org/D63750 llvm-svn: 365911
Diffstat (limited to 'llvm/lib/Support/Unix/Signals.inc')
-rw-r--r--llvm/lib/Support/Unix/Signals.inc67
1 files changed, 53 insertions, 14 deletions
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index ec3935928d2..634c16aa36c 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -42,6 +42,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Program.h"
+#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/UniqueLock.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -80,10 +81,13 @@
using namespace llvm;
static RETSIGTYPE SignalHandler(int Sig); // defined below.
+static RETSIGTYPE InfoSignalHandler(int Sig); // defined below.
+using SignalHandlerFunctionType = void (*)();
/// The function to call if ctrl-c is pressed.
-using InterruptFunctionType = void (*)();
-static std::atomic<InterruptFunctionType> InterruptFunction =
+static std::atomic<SignalHandlerFunctionType> InterruptFunction =
+ ATOMIC_VAR_INIT(nullptr);
+static std::atomic<SignalHandlerFunctionType> InfoSignalFunction =
ATOMIC_VAR_INIT(nullptr);
namespace {
@@ -199,15 +203,15 @@ struct FilesToRemoveCleanup {
static StringRef Argv0;
-// Signals that represent requested termination. There's no bug or failure, or
-// if there is, it's not our direct responsibility. For whatever reason, our
-// continued execution is no longer desirable.
+/// Signals that represent requested termination. There's no bug or failure, or
+/// 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, SIGUSR1, SIGUSR2
+ SIGHUP, SIGINT, SIGPIPE, SIGTERM, SIGUSR2
};
-// Signals that represent that we have a bug, and our prompt termination has
-// been ordered.
+/// Signals that represent that we have a bug, and our prompt termination has
+/// been ordered.
static const int KillSigs[] = {
SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT
#ifdef SIGSYS
@@ -224,11 +228,24 @@ static const int KillSigs[] = {
#endif
};
+/// Signals that represent requests for status.
+static const int InfoSigs[] = {
+ SIGUSR1
+#ifdef SIGINFO
+ , SIGINFO
+#endif
+};
+
+static const size_t NumSigs =
+ array_lengthof(IntSigs) + array_lengthof(KillSigs) +
+ array_lengthof(InfoSigs);
+
+
static std::atomic<unsigned> NumRegisteredSignals = ATOMIC_VAR_INIT(0);
static struct {
struct sigaction SA;
int SigNo;
-} RegisteredSignalInfo[array_lengthof(IntSigs) + array_lengthof(KillSigs)];
+} RegisteredSignalInfo[NumSigs];
#if defined(HAVE_SIGALTSTACK)
// Hold onto both the old and new alternate signal stack so that it's not
@@ -276,15 +293,24 @@ static void RegisterHandlers() { // Not signal-safe.
// be able to reliably handle signals due to stack overflow.
CreateSigAltStack();
- auto registerHandler = [&](int Signal) {
+ enum class SignalKind { IsKill, IsInfo };
+ auto registerHandler = [&](int Signal, SignalKind Kind) {
unsigned Index = NumRegisteredSignals.load();
assert(Index < array_lengthof(RegisteredSignalInfo) &&
"Out of space for signal handlers!");
struct sigaction NewHandler;
- NewHandler.sa_handler = SignalHandler;
- NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
+ switch (Kind) {
+ case SignalKind::IsKill:
+ NewHandler.sa_handler = SignalHandler;
+ NewHandler.sa_flags = SA_NODEFER | SA_RESETHAND | SA_ONSTACK;
+ break;
+ case SignalKind::IsInfo:
+ NewHandler.sa_handler = InfoSignalHandler;
+ NewHandler.sa_flags = SA_ONSTACK;
+ break;
+ }
sigemptyset(&NewHandler.sa_mask);
// Install the new handler, save the old one in RegisteredSignalInfo.
@@ -294,9 +320,11 @@ static void RegisterHandlers() { // Not signal-safe.
};
for (auto S : IntSigs)
- registerHandler(S);
+ registerHandler(S, SignalKind::IsKill);
for (auto S : KillSigs)
- registerHandler(S);
+ registerHandler(S, SignalKind::IsKill);
+ for (auto S : InfoSigs)
+ registerHandler(S, SignalKind::IsInfo);
}
static void UnregisterHandlers() {
@@ -356,6 +384,12 @@ static RETSIGTYPE SignalHandler(int Sig) {
#endif
}
+static RETSIGTYPE InfoSignalHandler(int Sig) {
+ SaveAndRestore<int> SaveErrnoDuringASignalHandler(errno);
+ if (SignalHandlerFunctionType CurrentInfoFunction = InfoSignalFunction)
+ CurrentInfoFunction();
+}
+
void llvm::sys::RunInterruptHandlers() {
RemoveFilesToRemove();
}
@@ -365,6 +399,11 @@ void llvm::sys::SetInterruptFunction(void (*IF)()) {
RegisterHandlers();
}
+void llvm::sys::SetInfoSignalFunction(void (*Handler)()) {
+ InfoSignalFunction.exchange(Handler);
+ RegisterHandlers();
+}
+
// The public API
bool llvm::sys::RemoveFileOnSignal(StringRef Filename,
std::string* ErrMsg) {
OpenPOWER on IntegriCloud