diff options
Diffstat (limited to 'llvm/lib/Support/Unix')
| -rw-r--r-- | llvm/lib/Support/Unix/Signals.inc | 67 | 
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) {  | 

