CMS 3D CMS Logo

UnixSignalHandlers.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <iomanip>
3 #include <cstdlib>
4 #include <cstdio>
5 #include <cstring>
6 
9 
10 #if !defined(NSIG)
11 #if defined(_NSIG)
12 #define NSIG _NSIG
13 #elif defined(__DARWIN_NSIG)
14 #define NSIG __DARWIN_NSIG
15 #endif
16 #endif
17 
18 namespace edm {
19 
20  //--------------------------------------------------------------
21 
22  volatile std::atomic<bool> shutdown_flag{false};
23 
24  extern "C" {
25  void ep_sigusr2(int, siginfo_t*, void*) {
26  FDEBUG(1) << "in sigusr2 handler\n";
27  shutdown_flag.store(true);
28  }
29  }
30 #define MUST_BE_ZERO(fun) \
31  if ((fun) != 0) { \
32  perror("UnixSignalHandlers::setupSignal: sig function failed"); \
33  abort(); \
34  }
35 
36  //--------------------------------------------------------------
37 
38  void disableAllSigs(sigset_t* oldset) {
39  sigset_t myset;
40  // all blocked for now
41  MUST_BE_ZERO(sigfillset(&myset));
42  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &myset, oldset));
43  }
44 
45  //--------------------------------------------------------------
46 
47  void disableRTSigs() {
48 #if defined(__linux__)
49  // ignore all the RT signals
50  sigset_t myset;
51  MUST_BE_ZERO(sigemptyset(&myset));
52 
53  struct sigaction tmpact;
54  memset(&tmpact, 0, sizeof(tmpact));
55  tmpact.sa_handler = SIG_IGN;
56 
57  for (int num = SIGRTMIN; num <= SIGRTMAX; ++num) {
58  // signal 38 is used by Intel Amplifier
59  if (num == 38)
60  continue;
61 
62  MUST_BE_ZERO(sigaddset(&myset, num));
63  MUST_BE_ZERO(sigaction(num, &tmpact, nullptr));
64  }
65 
66  MUST_BE_ZERO(pthread_sigmask(SIG_BLOCK, &myset, nullptr));
67 #endif
68  }
69 
70  //--------------------------------------------------------------
71 
72  void reenableSigs(sigset_t* oldset) {
73  // reenable the signals
74  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, oldset, nullptr));
75  }
76 
77  //--------------------------------------------------------------
78 
79  void enableSignal(sigset_t* newset, const int signum) {
80  // enable the specified signal
81  MUST_BE_ZERO(sigaddset(newset, signum));
82  }
83 
84  //--------------------------------------------------------------
85 
86  void disableSignal(sigset_t* newset, const int signum) {
87  // disable the specified signal
88  MUST_BE_ZERO(sigdelset(newset, signum));
89  }
90 
91  //--------------------------------------------------------------
92 
93  void installCustomHandler(const int signum, CFUNC func) {
94  sigset_t oldset;
95  edm::disableAllSigs(&oldset);
96 #if defined(__linux__)
98 #endif
99  edm::installSig(signum, func);
100  edm::reenableSigs(&oldset);
101  }
102 
103  //--------------------------------------------------------------
104 
105  void installSig(const int signum, CFUNC func) {
106  // set up my RT signal now
107  struct sigaction act;
108  memset(&act, 0, sizeof(act));
109  act.sa_sigaction = func;
110  act.sa_flags = SA_RESTART;
111 
112  // get my signal number
113  int mysig = signum;
114  if (mysig == SIGKILL) {
115  perror("Cannot install handler for KILL signal");
116  return;
117  } else if (mysig == SIGSTOP) {
118  perror("Cannot install handler for STOP signal");
119  return;
120  }
121 
122  if (sigaction(mysig, &act, nullptr) != 0) {
123  perror("sigaction failed");
124  abort();
125  }
126 
127  sigset_t newset;
128  MUST_BE_ZERO(sigemptyset(&newset));
129  MUST_BE_ZERO(sigaddset(&newset, mysig));
130  MUST_BE_ZERO(pthread_sigmask(SIG_UNBLOCK, &newset, nullptr));
131  }
132 
133  //--------------------------------------------------------------
134 
135  void sigInventory() {
136  sigset_t tmpset, oldset;
137  // Make a full house set of signals, except for SIGKILL = 9
138  // and SIGSTOP = 19 which cannot be blocked
139  MUST_BE_ZERO(sigfillset(&tmpset));
140  MUST_BE_ZERO(sigdelset(&tmpset, SIGKILL));
141  MUST_BE_ZERO(sigdelset(&tmpset, SIGSTOP));
142  // Swap it with the current sigset_t
143  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &tmpset, &oldset));
144  // Now see what's included in the set
145  for (int k = 1; k < NSIG; ++k) {
146  std::cerr << "sigismember is " << sigismember(&tmpset, k) << " for signal " << std::setw(2) << k
147 #if defined(__linux__)
148  << " (" << strsignal(k) << ")"
149 #endif
150  << std::endl;
151  }
152  // Finally put the original sigset_t back
153  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &oldset, &tmpset));
154  }
155 
156 } // end of namespace edm
void installSig(int signum, CFUNC func)
void disableAllSigs(sigset_t *oldset)
volatile std::atomic< bool > shutdown_flag
void installCustomHandler(int signum, CFUNC func)
#define FDEBUG(lev)
Definition: DebugMacros.h:19
void enableSignal(sigset_t *newset, int signum)
void reenableSigs(sigset_t *oldset)
void disableSignal(sigset_t *newset, int signum)
void sigInventory()
void(* CFUNC)(int, siginfo_t *, void *)
HLT enums.
void ep_sigusr2(int, siginfo_t *, void *)
#define MUST_BE_ZERO(fun)
void disableRTSigs()