LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
UnixSignalHandlers.cc
Go to the documentation of this file.
2 
4 
5 #include <cstddef>
6 #include <cstdlib>
7 #include <exception>
8 #include <iomanip>
9 #include <iostream>
10 #include <stdio.h>
11 #include <string.h>
12 
13 #if !defined(NSIG)
14 #if defined(_NSIG)
15 #define NSIG _NSIG
16 #elif defined(__DARWIN_NSIG)
17 #define NSIG __DARWIN_NSIG
18 #endif
19 #endif
20 
21 namespace art {
22 
23  std::mutex usr2_lock;
24 
25  //--------------------------------------------------------------
26 
27  std::atomic<int> shutdown_flag{0};
28 
29  extern "C" {
30  void
31  ep_sigusr2(int which, siginfo_t*, void*)
32  {
33  FDEBUG(1) << "in sigusr2 handler\n";
34  if (which == SIGINT && shutdown_flag > 0) {
35  std::cerr << "User signal SIGINT terminating the process\n";
36  std::terminate();
37  }
38  shutdown_flag = which;
39  }
40  }
41 
42  //--------------------------------------------------------------
43 
44  std::mutex signum_lock;
45  volatile int signum_value =
46 #if defined(__linux__)
47  SIGRTMIN;
48 #else
49  0;
50 #endif
51 
52  //--------------------------------------------------------------
53 
54  int
56  {
57  std::lock_guard<decltype(signum_lock)> lock{signum_lock};
58  int const rc{signum_value};
59  ++signum_value;
60  return rc;
61  }
62 
63 #define MUST_BE_ZERO(fun) \
64  if ((fun) != 0) { \
65  perror("UnixSignalHandlers::setupSignal: sig function failed"); \
66  abort(); \
67  }
68 
69  //--------------------------------------------------------------
70 
71  void
72  disableAllSigs(sigset_t* oldset)
73  {
74  sigset_t myset;
75  // all blocked for now
76  MUST_BE_ZERO(sigfillset(&myset));
77  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &myset, oldset));
78  }
79 
80  //--------------------------------------------------------------
81 
82  void
84  {
85 #if defined(__linux__)
86  // ignore all the RT signals
87  sigset_t myset;
88  MUST_BE_ZERO(sigemptyset(&myset));
89 
90  struct sigaction tmpact;
91  memset(&tmpact, 0, sizeof(tmpact));
92  tmpact.sa_handler = SIG_IGN;
93 
94  for (int num = SIGRTMIN; num < SIGRTMAX; ++num) {
95  MUST_BE_ZERO(sigaddset(&myset, num));
96  MUST_BE_ZERO(sigaction(num, &tmpact, nullptr));
97  }
98 
99  MUST_BE_ZERO(pthread_sigmask(SIG_BLOCK, &myset, 0));
100 #endif
101  }
102 
103  //--------------------------------------------------------------
104 
105  void
106  reenableSigs(sigset_t* oldset)
107  {
108  // reenable the signals
109  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, oldset, 0));
110  }
111 
112  //--------------------------------------------------------------
113 
114  void
115  enableSignal(sigset_t* newset, const int signum)
116  {
117  // enable the specified signal
118  MUST_BE_ZERO(sigaddset(newset, signum));
119  }
120 
121  //--------------------------------------------------------------
122 
123  void
124  disableSignal(sigset_t* newset, const int signum)
125  {
126  // disable the specified signal
127  MUST_BE_ZERO(sigdelset(newset, signum));
128  }
129 
130  //--------------------------------------------------------------
131 
132  void
133  installCustomHandler(const int signum, CFUNC func)
134  {
135  sigset_t oldset;
136  art::disableAllSigs(&oldset);
137 #if defined(__linux__)
139 #endif
140  art::installSig(signum, func);
141  art::reenableSigs(&oldset);
142  }
143 
144  //--------------------------------------------------------------
145 
146  void
147  installSig(const int signum, CFUNC func)
148  {
149  // set up my RT signal now
150  struct sigaction act;
151  memset(&act, 0, sizeof(act));
152  act.sa_sigaction = func;
153  act.sa_flags = SA_RESTART;
154 
155  // get my signal number
156  int mysig = signum;
157  if (mysig == SIGKILL) {
158  perror("Cannot install handler for KILL signal");
159  return;
160  } else if (mysig == SIGSTOP) {
161  perror("Cannot install handler for STOP signal");
162  return;
163  }
164 
165  if (sigaction(mysig, &act, nullptr) != 0) {
166  perror("sigaction failed");
167  abort();
168  }
169 
170  sigset_t newset;
171  MUST_BE_ZERO(sigemptyset(&newset));
172  MUST_BE_ZERO(sigaddset(&newset, mysig));
173  MUST_BE_ZERO(pthread_sigmask(SIG_UNBLOCK, &newset, 0));
174  }
175 
176  //--------------------------------------------------------------
177 
178  void
180  {
181  sigset_t tmpset, oldset;
182  // Make a full house set of signals, except for SIGKILL = 9
183  // and SIGSTOP = 19 which cannot be blocked
184  MUST_BE_ZERO(sigfillset(&tmpset));
185  MUST_BE_ZERO(sigdelset(&tmpset, SIGKILL));
186  MUST_BE_ZERO(sigdelset(&tmpset, SIGSTOP));
187  // Swap it with the current sigset_t
188  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &tmpset, &oldset));
189  // Now see what's included in the set
190  for (int k = 1; k < NSIG; ++k) {
191  std::cerr << "sigismember is " << sigismember(&tmpset, k)
192  << " for signal " << std::setw(2) << k
193 #if defined(__linux__)
194  << " (" << strsignal(k) << ")"
195 #endif
196  << std::endl;
197  }
198  // Finally put the original sigset_t back
199  MUST_BE_ZERO(pthread_sigmask(SIG_SETMASK, &oldset, &tmpset));
200  }
201 
202  void
203  setupSignals(bool want_sigint_enabled)
204  {
208  if (want_sigint_enabled)
210  }
211 
212 } // art
std::atomic< int > shutdown_flag
void disableSignal(sigset_t *newset, const int signum)
void reenableSigs(sigset_t *oldset)
volatile int signum_value
void sigInventory()
void disableRTSigs()
void disableAllSigs(sigset_t *oldset)
std::mutex signum_lock
int getSigNum()
std::mutex usr2_lock
void setupSignals(bool want_sigint_enabled)
void ep_sigusr2(int which, siginfo_t *, void *)
HLT enums.
void(*)(int, siginfo_t *, void *) CFUNC
#define FDEBUG(lev)
Definition: DebugMacros.h:26
void installCustomHandler(const int signum, CFUNC func)
#define MUST_BE_ZERO(fun)
void enableSignal(sigset_t *newset, const int signum)
void installSig(const int signum, CFUNC func)