ATLAS Offline Software
Typedefs | Functions | Variables
CoreDumpSvcHandler Namespace Reference

Signal handler for CoreDumpSvc. More...

Typedefs

typedef std::map< int, struct sigaction > SigHandler_t
 

Functions

bool callOldHandler (true)
 forward calls to old handlers? More...
 
bool dumpCoreFile (false)
 dump core file on exit? More...
 
bool stackTrace (false)
 produce stack trace? More...
 
bool fastStackTrace (false)
 produce fast stack trace using CxxUtils/Seal More...
 
CoreDumpSvccoreDumpSvc (nullptr)
 pointer to CoreDumpSvc More...
 
std::ostream &log ATLAS_NOT_THREAD_SAFE ()
 convenience method for logging More...
 
void action ATLAS_NOT_THREAD_SAFE (int sig, siginfo_t *info, void *extra)
 Signal handler for the CoreDumpSvc. More...
 

Variables

SigHandler_t oldSigHandler
 old signal handlers More...
 

Detailed Description

Signal handler for CoreDumpSvc.

All information accessible from the signal handler is in this namespace. It carries a pointer to the CoreDumpSvc instance. Therefore no static methods are needed in the CoreDumpSvc to provide a function pointer.

Typedef Documentation

◆ SigHandler_t

typedef std::map<int, struct sigaction> CoreDumpSvcHandler::SigHandler_t

Definition at line 79 of file CoreDumpSvc.cxx.

Function Documentation

◆ ATLAS_NOT_THREAD_SAFE() [1/2]

std::ostream& log CoreDumpSvcHandler::ATLAS_NOT_THREAD_SAFE ( )

convenience method for logging

Definition at line 89 of file CoreDumpSvc.cxx.

◆ ATLAS_NOT_THREAD_SAFE() [2/2]

void action CoreDumpSvcHandler::ATLAS_NOT_THREAD_SAFE ( int  sig,
siginfo_t info,
void *  extra 
)

Signal handler for the CoreDumpSvc.

Definition at line 94 of file CoreDumpSvc.cxx.

95  {
96  // Careful: don't do anything here that might allocate memory.
97 
98  // Protect against recursion.
99  // We originally used a thread_local here --- but accessing
100  // a thread_local can result in a call to malloc.
101 
102  const int maxcalls = 64;
103  static std::atomic<int> ncalls (0);
104  if (++ncalls >= maxcalls) _exit (98);
105 
106  static std::mutex tidlist_mutex;
107  static size_t ntids ATLAS_THREAD_SAFE = 0;
108  static pthread_t tids[maxcalls] ATLAS_THREAD_SAFE;
109  {
110  pthread_t self = pthread_self();
111  std::lock_guard<std::mutex> lock (tidlist_mutex);
112  for (size_t i = 0; i < ntids; i++) {
113  if (pthread_equal (self, tids[i])) return;
114  }
115  if (ntids == maxcalls) _exit (98);
116  tids[ntids++] = self;
117  }
118 
119  // Count the number of threads trying to dump.
120  static std::atomic<int> inThreads = 0;
121  ++inThreads;
122 
123  const unsigned int timeoutSeconds = static_cast<unsigned int>(round(coreDumpSvc->m_timeout * 1e-9));
124 
125  if ( sig == SIGALRM) {
126  if (dumpCoreFile) {
127  log() << "Received SIGALRM. Aborting job..." << std::endl;
128  // Restore default abort handler that should create a core file
129  Athena::Signal::revert (SIGABRT);
130  std::abort();
131  }
132  else {
133  log() << "Received SIGALRM. Terminating job..." << std::endl;
134  _exit(97); // exit without raising any further signals
135  }
136  }
137 
138  // Only allow one thread past at a time.
139  // Try to assume as little as possible about the state of the library.
140  // We don't want to hang forever here, but we also don't want
141  // to call any library functions that might use signals under the hood.
142  // So use nanosleep() to do the delay --- that's defined to be
143  // independent of signals.
144  static std::mutex threadMutex;
145  const timespec one_second { 1, 0 };
146  {
147  unsigned int waits = 0;
148  while (!threadMutex.try_lock()) {
149  nanosleep (&one_second, nullptr);
150  if (++waits > timeoutSeconds) _exit (97);
151  }
152  }
153 
154  // setup timeout
155  if ( timeoutSeconds > 0 && (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT) ) {
156  // This will trigger SIGALRM, which we then handle ourselves above
157  alarm(timeoutSeconds);
158  }
159 
160  // Do fast stack trace before anything that might touch the heap.
161  // For extra paranoia, avoid iostreams/stdio and use write() directly.
162  if (fastStackTrace) {
163  write (1, horizLine, strlen(horizLine));
164  const char* msg = "Producing (fast) stack trace...\n";
165  write (1, msg, strlen (msg));
166  write (1, horizLine, strlen(horizLine));
167  Athena::Signal::fatalDump (sig, info, extra,
172  write (1, "\n", 1);
173  }
174 
175  std::cout.flush();
176  std::cerr.flush();
177 
178  if (coreDumpSvc) {
180  coreDumpSvc->print();
181  }
182 
183  if (gSystem && stackTrace) {
184  log() << horizLine << "Producing stack trace (can be slow, check gdb process)...\n"
185  << horizLine << std::flush;
186  gSystem->StackTrace();
187  log() << std::endl;
188  }
189 
190  if (callOldHandler) {
191  // Call previous signal handler
192  // Need to distinguish between the two different types
193  const struct sigaction& oact = oldSigHandler[sig];
194  log() << horizLine << "Invoking previous signal handler (can be slow, check gdb process)...\n"
195  << horizLine << std::flush;
196  if ( oact.sa_flags & SA_SIGINFO ) {
197  oact.sa_sigaction(sig, info, extra);
198  }
199  else if (oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN ) {
200  oact.sa_handler(sig);
201  }
202  else {
203  log() << "Could not invoke previous signal handler" << std::endl;
204  }
205  }
206 
207  // This thread is done dumping.
208  threadMutex.unlock();
209  --inThreads;
210 
211  if (coreDumpSvc && (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT) ) {
212  // Don't terminate the program while there are other threads
213  // trying to dump (but don't wait forever either).
214  unsigned int waits = 0;
215  while (inThreads > 0 && waits < timeoutSeconds) {
216  nanosleep (&one_second, nullptr);
217  }
218 
219  if (dumpCoreFile) {
220  log() << "Aborting job... " << std::endl;
221  // Restore default abort handler that should create a core file
222  Athena::Signal::revert (SIGABRT);
223  std::abort();
224  }
225 
226  // Exit now on a fatal signal; otherwise, we can hang.
227  _exit (99);
228  }
229  }

◆ callOldHandler()

bool CoreDumpSvcHandler::callOldHandler ( true  )

forward calls to old handlers?

◆ coreDumpSvc()

CoreDumpSvc* CoreDumpSvcHandler::coreDumpSvc ( nullptr  )

pointer to CoreDumpSvc

◆ dumpCoreFile()

bool CoreDumpSvcHandler::dumpCoreFile ( false  )

dump core file on exit?

◆ fastStackTrace()

bool CoreDumpSvcHandler::fastStackTrace ( false  )

produce fast stack trace using CxxUtils/Seal

◆ stackTrace()

bool CoreDumpSvcHandler::stackTrace ( false  )

produce stack trace?

Variable Documentation

◆ oldSigHandler

SigHandler_t CoreDumpSvcHandler::oldSigHandler

old signal handlers

Definition at line 81 of file CoreDumpSvc.cxx.

grepfile.info
info
Definition: grepfile.py:38
CoreDumpSvcHandler::oldSigHandler
SigHandler_t oldSigHandler
old signal handlers
Definition: CoreDumpSvc.cxx:81
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
Athena::Signal::FATAL_DUMP_STACK
static const int FATAL_DUMP_STACK
Option to make #fataldump(int, siginfo_t *, void *) (invoked by #fatal(int, siginfo_t *,...
Definition: SealSignal.h:130
FullCPAlgorithmsTest_eljob.flush
flush
Definition: FullCPAlgorithmsTest_eljob.py:186
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
MuonGM::round
float round(const float toRound, const unsigned int decimals)
Definition: Mdt.cxx:27
CoreDumpSvcHandler::dumpCoreFile
bool dumpCoreFile(false)
dump core file on exit?
CoreDumpSvcHandler::fastStackTrace
bool fastStackTrace(false)
produce fast stack trace using CxxUtils/Seal
Athena::Signal::FATAL_DUMP_SIG
static const int FATAL_DUMP_SIG
Option to make #fataldump(int, siginfo_t *, void *) (invoked by #fatal(int, siginfo_t *,...
Definition: SealSignal.h:126
CoreDumpSvc::m_timeout
Gaudi::Property< double > m_timeout
Definition: CoreDumpSvc.h:120
lumiFormat.i
int i
Definition: lumiFormat.py:85
CoreDumpSvcHandler::coreDumpSvc
CoreDumpSvc * coreDumpSvc(nullptr)
pointer to CoreDumpSvc
python.ByteStreamConfig.write
def write
Definition: Event/ByteStreamCnvSvc/python/ByteStreamConfig.py:248
python.BuildSignatureFlags.sig
sig
Definition: BuildSignatureFlags.py:218
Athena::DebugAids::stacktraceFd
static IOFD stacktraceFd(IOFD fd=IOFD_INVALID)
Set and return the file descriptor for stack trace output.
Definition: SealDebug.cxx:604
Athena::Signal::FATAL_DUMP_CONTEXT
static const int FATAL_DUMP_CONTEXT
Option to make #fataldump(int, siginfo_t *, void *) (invoked by #fatal(int, siginfo_t *,...
Definition: SealSignal.h:138
CoreDumpSvc::setSigInfo
void setSigInfo(siginfo_t *info)
Set pointer to siginfo_t struct.
Definition: CoreDumpSvc.h:136
python.handimod.extra
int extra
Definition: handimod.py:522
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
CoreDumpSvcHandler::callOldHandler
bool callOldHandler(true)
forward calls to old handlers?
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
Athena::Signal::revert
static void revert(int sig)
Revert the signal number sig back to its default behaviour.
Definition: SealSignal.cxx:326
CoreDumpSvcHandler::stackTrace
bool stackTrace(false)
produce stack trace?
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7