Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:14

0001 #include <iostream>
0002 #include <iomanip>
0003 #include <cstdlib>
0004 #include <cstdio>
0005 #include <cstring>
0006 
0007 #include "FWCore/Utilities/interface/UnixSignalHandlers.h"
0008 #include "FWCore/Utilities/interface/DebugMacros.h"
0009 
0010 #if !defined(NSIG)
0011 #if defined(_NSIG)
0012 #define NSIG _NSIG
0013 #elif defined(__DARWIN_NSIG)
0014 #define NSIG __DARWIN_NSIG
0015 #endif
0016 #endif
0017 
0018 namespace edm {
0019 
0020   //--------------------------------------------------------------
0021 
0022   volatile std::atomic<bool> shutdown_flag{false};
0023 
0024   extern "C" {
0025   void ep_sigusr2(int, siginfo_t*, void*) {
0026     FDEBUG(1) << "in sigusr2 handler\n";
0027     shutdown_flag.store(true);
0028   }
0029   }
0030 #define MUST_BE_ZERO(fun)                                           \
0031   if ((fun) != 0) {                                                 \
0032     perror("UnixSignalHandlers::setupSignal: sig function failed"); \
0033     abort();                                                        \
0034   }
0035 
0036   //--------------------------------------------------------------
0037 
0038   void disableAllSigs(sigset_t* oldset) {
0039     sigset_t myset;
0040     // all blocked for now
0041     MUST_BE_ZERO(sigfillset(&myset));
0042     MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &myset, oldset));
0043   }
0044 
0045   //--------------------------------------------------------------
0046 
0047   void disableRTSigs() {
0048 #if defined(__linux__)
0049     // ignore all the RT signals
0050     sigset_t myset;
0051     MUST_BE_ZERO(sigemptyset(&myset));
0052 
0053     struct sigaction tmpact;
0054     memset(&tmpact, 0, sizeof(tmpact));
0055     tmpact.sa_handler = SIG_IGN;
0056 
0057     for (int num = SIGRTMIN; num <= SIGRTMAX; ++num) {
0058       // signal 38 is used by Intel Amplifier
0059       if (num == 38)
0060         continue;
0061 
0062       MUST_BE_ZERO(sigaddset(&myset, num));
0063       MUST_BE_ZERO(sigaction(num, &tmpact, nullptr));
0064     }
0065 
0066     MUST_BE_ZERO(pthread_sigmask(SIG_BLOCK, &myset, nullptr));
0067 #endif
0068   }
0069 
0070   //--------------------------------------------------------------
0071 
0072   void reenableSigs(sigset_t* oldset) {
0073     // reenable the signals
0074     MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, oldset, nullptr));
0075   }
0076 
0077   //--------------------------------------------------------------
0078 
0079   void enableSignal(sigset_t* newset, const int signum) {
0080     // enable the specified signal
0081     MUST_BE_ZERO(sigaddset(newset, signum));
0082   }
0083 
0084   //--------------------------------------------------------------
0085 
0086   void disableSignal(sigset_t* newset, const int signum) {
0087     // disable the specified signal
0088     MUST_BE_ZERO(sigdelset(newset, signum));
0089   }
0090 
0091   //--------------------------------------------------------------
0092 
0093   void installCustomHandler(const int signum, CFUNC func) {
0094     sigset_t oldset;
0095     edm::disableAllSigs(&oldset);
0096 #if defined(__linux__)
0097     edm::disableRTSigs();
0098 #endif
0099     edm::installSig(signum, func);
0100     edm::reenableSigs(&oldset);
0101   }
0102 
0103   //--------------------------------------------------------------
0104 
0105   void installSig(const int signum, CFUNC func) {
0106     // set up my RT signal now
0107     struct sigaction act;
0108     memset(&act, 0, sizeof(act));
0109     act.sa_sigaction = func;
0110     act.sa_flags = SA_RESTART;
0111 
0112     // get my signal number
0113     int mysig = signum;
0114     if (mysig == SIGKILL) {
0115       perror("Cannot install handler for KILL signal");
0116       return;
0117     } else if (mysig == SIGSTOP) {
0118       perror("Cannot install handler for STOP signal");
0119       return;
0120     }
0121 
0122     if (sigaction(mysig, &act, nullptr) != 0) {
0123       perror("sigaction failed");
0124       abort();
0125     }
0126 
0127     sigset_t newset;
0128     MUST_BE_ZERO(sigemptyset(&newset));
0129     MUST_BE_ZERO(sigaddset(&newset, mysig));
0130     MUST_BE_ZERO(pthread_sigmask(SIG_UNBLOCK, &newset, nullptr));
0131   }
0132 
0133   //--------------------------------------------------------------
0134 
0135   void sigInventory() {
0136     sigset_t tmpset, oldset;
0137     //    Make a full house set of signals, except for SIGKILL = 9
0138     //    and SIGSTOP = 19 which cannot be blocked
0139     MUST_BE_ZERO(sigfillset(&tmpset));
0140     MUST_BE_ZERO(sigdelset(&tmpset, SIGKILL));
0141     MUST_BE_ZERO(sigdelset(&tmpset, SIGSTOP));
0142     //    Swap it with the current sigset_t
0143     MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &tmpset, &oldset));
0144     //    Now see what's included in the set
0145     for (int k = 1; k < NSIG; ++k) {
0146       std::cerr << "sigismember is " << sigismember(&tmpset, k) << " for signal " << std::setw(2) << k
0147 #if defined(__linux__)
0148                 << " (" << strsignal(k) << ")"
0149 #endif
0150                 << std::endl;
0151     }
0152     //    Finally put the original sigset_t back
0153     MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &oldset, &tmpset));
0154   }
0155 
0156 }  // end of namespace edm