LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
UnixSignalHandlers.cc
Go to the documentation of this file.
1 
3 // vim: set sw=2 expandtab :
4 
6 
7 #include <atomic>
8 #include <csignal>
9 #include <cstdio>
10 #include <cstdlib>
11 #include <cstring>
12 #include <exception>
13 #include <iostream>
14 
15 using namespace std;
16 
17 using my_sigaction_func_t = void (*)(int, siginfo_t*, void*);
18 
19 atomic<int> art::shutdown_flag{0};
20 
21 extern "C" {
22 
23 static void
24 handle_sigusr2(int which, siginfo_t*, void*)
25 {
26  FDEBUG(1) << "in sigusr2 handler\n";
27  if ((which == SIGINT) && (art::shutdown_flag > 0)) {
28  cerr << "User signal SIGINT terminating the process\n";
29  terminate();
30  }
31  art::shutdown_flag = which;
32 }
33 
34 } // extern "C"
35 
36 namespace art {
37 
38  namespace {
39 
40  void
41  abort_on_error(int const errcode)
42  {
43  if (errcode != 0) {
44  perror("UnixSignalHandlers::setupSignal: sig function failed");
45  abort();
46  }
47  }
48 
49  void
50  reenableSigs(sigset_t* oldset)
51  {
52  abort_on_error(pthread_sigmask(SIG_SETMASK, oldset, 0));
53  }
54 
55  void
56  installSig(const int signum, my_sigaction_func_t func)
57  {
58  struct sigaction act;
59  memset(&act, 0, sizeof(act));
60  act.sa_sigaction = func;
61  act.sa_flags = SA_RESTART;
62  int mysig = signum;
63  if (mysig == SIGKILL) {
64  cerr << "Cannot install handler for KILL signal\n";
65  return;
66  } else if (mysig == SIGSTOP) {
67  cerr << "Cannot install handler for STOP signal\n";
68  return;
69  }
70  abort_on_error(sigaction(mysig, &act, nullptr));
71  sigset_t newset;
72  abort_on_error(sigemptyset(&newset));
73  abort_on_error(sigaddset(&newset, mysig));
74  abort_on_error(pthread_sigmask(SIG_UNBLOCK, &newset, 0));
75  }
76 
77 #ifdef __linux__
78  void
79  tweakRTSigs_(int how)
80  {
81  sigset_t myset;
82  abort_on_error(sigemptyset(&myset));
83  struct sigaction tmpact;
84  memset(&tmpact, 0, sizeof(tmpact));
85  tmpact.sa_handler = SIG_IGN;
86  for (int num = SIGRTMIN; num < SIGRTMAX; ++num) {
87  abort_on_error(sigaddset(&myset, num));
88  abort_on_error(sigaction(num, &tmpact, nullptr));
89  }
90  abort_on_error(pthread_sigmask(how, &myset, 0));
91  }
92 #endif // __linux__
93 
94  void
95  disableAllSigs(sigset_t* oldset)
96  {
97  sigset_t myset;
98  abort_on_error(sigfillset(&myset));
99  abort_on_error(pthread_sigmask(SIG_SETMASK, &myset, oldset));
100  }
101 
102  void
103  installCustomHandler(const int signum, my_sigaction_func_t func)
104  {
105  sigset_t oldset;
106  disableAllSigs(&oldset);
107 #ifdef __linux__
108  tweakRTSigs_(SIG_BLOCK);
109 #endif // __linux__
110  installSig(signum, func);
111 #ifdef __linux__
112  tweakRTSigs_(SIG_UNBLOCK);
113 #endif // __linux__
114  reenableSigs(&oldset);
115  }
116 
117  } // unnamed namespace
118 
119  void
120  setupSignals(bool want_sigint_enabled)
121  {
122  installCustomHandler(SIGUSR2, handle_sigusr2);
123  installCustomHandler(SIGTERM, handle_sigusr2);
124  installCustomHandler(SIGQUIT, handle_sigusr2);
125  if (want_sigint_enabled) {
126  installCustomHandler(SIGINT, handle_sigusr2);
127  }
128  }
129 
130 } // namespace art
STL namespace.
std::atomic< int > shutdown_flag
static void handle_sigusr2(int which, siginfo_t *, void *)
void setupSignals(bool want_sigint_enabled)
Definition: MVAAlg.h:12
#define FDEBUG(LEVEL)
Definition: DebugMacros.h:25
void(*)(int, siginfo_t *, void *) my_sigaction_func_t