CMS 3D CMS Logo

WorkerMonitorThread.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: FWCore/SharedMemory
4 // Class : WorkerMonitorThread
5 //
6 // Implementation:
7 // [Notes on implementation]
8 //
9 // Original Author: Chris Jones
10 // Created: 21/01/2020
11 //
12 
13 // system include files
14 #include <cerrno>
15 #include <csignal>
16 #include <iostream>
17 #include <unistd.h>
18 
19 // user include files
21 
22 //
23 // constants, enums and typedefs
24 //
25 using namespace edm::shared_memory;
26 
27 //
28 // static data member definitions
29 //
30 std::atomic<bool> WorkerMonitorThread::s_helperThreadDone = false;
31 std::atomic<int> WorkerMonitorThread::s_pipeReadEnd = 0;
32 std::atomic<int> WorkerMonitorThread::s_pipeWriteEnd = 0;
33 
34 //
35 // constructors and destructor
36 //
37 
38 //
39 // member functions
40 //
42  //std::cerr << "Started cleanup thread\n";
43  sigset_t ensemble;
44 
45  sigemptyset(&ensemble);
46  sigaddset(&ensemble, SIGABRT);
47  sigaddset(&ensemble, SIGILL);
48  sigaddset(&ensemble, SIGBUS);
49  sigaddset(&ensemble, SIGSEGV);
50  sigaddset(&ensemble, SIGTERM);
51  pthread_sigmask(SIG_BLOCK, &ensemble, nullptr);
52 
53  //std::cerr << "Start loop\n";
54  helperReady_ = true;
55  while (true) {
56  int signal = -1;
57  auto res = read(s_pipeReadEnd.load(), &signal, sizeof(signal) / sizeof(char));
58  if (res == -1) {
59  if (errno == EINTR) {
60  continue;
61  }
62  abort();
63  }
64  if (signal != 0) {
65  if (actionSet_) {
66  action_();
67  }
68  std::cerr << "Worker: SIGNAL CAUGHT " << signal << "\n";
69  s_helperThreadDone = true;
70  break;
71  } /* else {
72  std::cerr << "SIGNAL woke\n";
73  } */
74  }
75  //std::cerr << "Ending cleanup thread\n";
76 }
77 
79  {
80  //Setup watchdog thread for crashing signals
81 
82  int pipeEnds[2] = {0, 0};
83  auto ret = pipe(pipeEnds);
84  if (ret != 0) {
85  abort();
86  }
87  s_pipeReadEnd.store(pipeEnds[0]);
88  s_pipeWriteEnd.store(pipeEnds[1]);
89  //Need to use signal handler since signals generated
90  // from within a program are thread specific which can
91  // only be handed by a signal handler
93 
94  std::thread t(&WorkerMonitorThread::run, this);
95  t.detach();
97  }
98  while (helperReady_.load() == false) {
99  }
100 }
101 
103  struct sigaction act;
104  act.sa_sigaction = sig_handler;
105  act.sa_flags = SA_SIGINFO;
106  sigemptyset(&act.sa_mask);
107  sigaction(SIGABRT, &act, nullptr);
108  sigaction(SIGILL, &act, nullptr);
109  sigaction(SIGBUS, &act, nullptr);
110  sigaction(SIGSEGV, &act, nullptr);
111  sigaction(SIGTERM, &act, nullptr);
112 }
113 
115  stopRequested_ = true;
116  int sig = 0;
117  write(s_pipeWriteEnd.load(), &sig, sizeof(int) / sizeof(char));
118 }
119 
120 //
121 // const member functions
122 //
123 
124 //
125 // static member functions
126 //
127 void WorkerMonitorThread::sig_handler(int sig, siginfo_t*, void*) {
128  write(s_pipeWriteEnd.load(), &sig, sizeof(int) / sizeof(char));
129  while (not s_helperThreadDone) {
130  };
131  signal(sig, SIG_DFL);
132  raise(sig);
133 }
static std::atomic< bool > s_helperThreadDone
void setupSignalHandling()
Sets the unix signal handler which communicates with the thread.
Definition: Electron.h:6
static void sig_handler(int sig, siginfo_t *, void *)
def pipe(cmdline, input=None)
Definition: pipe.py:5
def write(self, setup)
def move(src, dest)
Definition: eostools.py:511