ATLAS Offline Software
Loading...
Searching...
No Matches
CoreDumpSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
11
12// System includes
13#include <ctime>
14#include <cstdio>
15#include <fcntl.h>
16#include <errno.h>
17#include <signal.h>
18#include <time.h>
19#include <sys/types.h>
20#ifndef __APPLE__
21#include <sys/sysinfo.h>
22#else
23#include <mach/task.h>
24#include <mach/mach_init.h>
25#include <unistd.h>
26#endif
27
28// Package includes
29#include "CoreDumpSvc.h"
30
31// ROOT includes
32#include "TSystem.h"
33
34// Gaudi includes
35#include "Gaudi/Property.h"
36#include "GaudiKernel/IAlgorithm.h"
37#include "GaudiKernel/IIncidentSvc.h"
38#include "GaudiKernel/IAlgContextSvc.h"
39#include "GaudiKernel/IAlgExecStateSvc.h"
40#include "GaudiKernel/IAlgManager.h"
41#include "GaudiKernel/ServiceHandle.h"
42#include "GaudiKernel/System.h"
43#include "GaudiKernel/ConcurrencyFlags.h"
44#include "GaudiKernel/EventContext.h"
45
46// Athena includes
49#include "CxxUtils/SealCommon.h"
50#include "CxxUtils/SealSignal.h"
51#include "CxxUtils/SealDebug.h"
54
55namespace {
56
57 const char* const horizLine = "-------------------------------------------------------------------------------------\n";
58
59 void ExitOnInt( int sig, siginfo_t*, void* ) {
60 if ( sig == SIGINT ) {
61 // called on user ^C
62 std::cout << std::endl;
63 std::cerr << "Athena CRITICAL stopped by user interrupt\n";
64 raise(SIGKILL);
65 }
66 }
67
68} // unnamed namespace
69
70
79{
80 typedef std::map<int, struct sigaction> SigHandler_t;
81
83 bool callOldHandler(true);
84 bool dumpCoreFile(false);
85 bool stackTrace(false);
86 bool fastStackTrace(false);
88 std::ostream* ostr(&std::cout);
89
90 std::ostream& log ATLAS_NOT_THREAD_SAFE () { return *ostr; }
91
95 void action ATLAS_NOT_THREAD_SAFE ( int sig, siginfo_t *info, void* extra )
96 {
97 // Careful: don't do anything here that might allocate memory.
98
99 // Protect against recursion.
100 // We originally used a thread_local here --- but accessing
101 // a thread_local can result in a call to malloc.
102
103 const int maxcalls = 64;
104 static std::atomic<int> ncalls (0);
105 if (++ncalls >= maxcalls) _exit (98);
106
107 static std::mutex tidlist_mutex;
108 static size_t ntids ATLAS_THREAD_SAFE = 0;
109 static pthread_t tids[maxcalls] ATLAS_THREAD_SAFE;
110 {
111 pthread_t self = pthread_self();
112 std::lock_guard<std::mutex> lock (tidlist_mutex);
113 for (size_t i = 0; i < ntids; i++) {
114 if (pthread_equal (self, tids[i])) return;
115 }
116 if (ntids == maxcalls) _exit (98);
117 tids[ntids++] = self;
118 }
119
120 // Count the number of threads trying to dump.
121 static std::atomic<int> inThreads = 0;
122 ++inThreads;
123
124 const unsigned int timeoutSeconds = static_cast<unsigned int>(round(coreDumpSvc->m_timeout * 1e-9));
125
126 if ( sig == SIGALRM) {
127 if (dumpCoreFile) {
128 log() << "Received SIGALRM. Aborting job..." << std::endl;
129 // Restore default abort handler that should create a core file
130 Athena::Signal::revert (SIGABRT);
131 std::abort();
132 }
133 else {
134 log() << "Received SIGALRM. Terminating job..." << std::endl;
135 _exit(97); // exit without raising any further signals
136 }
137 }
138
139 // Only allow one thread past at a time.
140 // Try to assume as little as possible about the state of the library.
141 // We don't want to hang forever here, but we also don't want
142 // to call any library functions that might use signals under the hood.
143 // So use nanosleep() to do the delay --- that's defined to be
144 // independent of signals.
145 static std::mutex threadMutex;
146 const timespec one_second { 1, 0 };
147 {
148 unsigned int waits = 0;
149 while (!threadMutex.try_lock()) {
150 nanosleep (&one_second, nullptr);
151 if (++waits > timeoutSeconds) _exit (97);
152 }
153 }
154
155 // setup timeout
156 if ( timeoutSeconds > 0 && (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT) ) {
157 // This will trigger SIGALRM, which we then handle ourselves above
158 alarm(timeoutSeconds);
159 }
160
161 // Do fast stack trace before anything that might touch the heap.
162 // For extra paranoia, avoid iostreams/stdio and use write() directly.
163 if (fastStackTrace) {
164 write (1, horizLine, strlen(horizLine));
165 const char* msg = "Producing (fast) stack trace...\n";
166 write (1, msg, strlen (msg));
167 write (1, horizLine, strlen(horizLine));
168 Athena::Signal::fatalDump (sig, info, extra,
173 write (1, "\n", 1);
174 }
175
176 std::cout.flush();
177 std::cerr.flush();
178
179 if (coreDumpSvc) {
180 coreDumpSvc->setSigInfo(info);
181 coreDumpSvc->print();
182 }
183
184 if (gSystem && stackTrace) {
185 log() << horizLine << "Producing stack trace (can be slow, check gdb process)...\n"
186 << horizLine << std::flush;
187 gSystem->StackTrace();
188 log() << std::endl;
189 }
190
191 if (callOldHandler) {
192 // Call previous signal handler
193 // Need to distinguish between the two different types
194 const struct sigaction& oact = oldSigHandler[sig];
195 log() << horizLine << "Invoking previous signal handler (can be slow, check gdb process)...\n"
196 << horizLine << std::flush;
197 if ( oact.sa_flags & SA_SIGINFO ) {
198 oact.sa_sigaction(sig, info, extra);
199 }
200 else if (oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN ) {
201 oact.sa_handler(sig);
202 }
203 else {
204 log() << "Could not invoke previous signal handler" << std::endl;
205 }
206 }
207
208 // This thread is done dumping.
209 threadMutex.unlock();
210 --inThreads;
211
212 if (coreDumpSvc && (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT) ) {
213 // Don't terminate the program while there are other threads
214 // trying to dump (but don't wait forever either).
215 unsigned int waits = 0;
216 while (inThreads > 0 && waits < timeoutSeconds) {
217 nanosleep (&one_second, nullptr);
218 }
219
220 if (dumpCoreFile) {
221 log() << "Aborting job... " << std::endl;
222 // Restore default abort handler that should create a core file
223 Athena::Signal::revert (SIGABRT);
224 std::abort();
225 }
226
227 // Exit now on a fatal signal; otherwise, we can hang.
228 _exit (99);
229 }
230 }
231
232}
233
234//================================================================================
235// C'tor, D'tor, Property handler
236//================================================================================
237CoreDumpSvc::CoreDumpSvc( const std::string& name, ISvcLocator* pSvcLocator ) :
238 base_class( name, pSvcLocator )
239{
240 // Set us as the current instance
242
243 m_callOldHandler.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
244 m_dumpCoreFile.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
245 m_stackTrace.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
246 m_fastStackTrace.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
247 m_coreDumpStream.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
248 m_fatalHandlerFlags.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
249 m_killOnSigInt.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
250 // Allocate for 2 slots just for now.
251 m_usrCoreDumps.resize(2);
252 m_sysCoreDumps.resize(2);
253}
254
259
260void CoreDumpSvc::propertyHandler(Gaudi::Details::PropertyBase& p)
261{
266
267 if ( p.name()==m_coreDumpStream.name() ) {
268 const std::string val = p.toString();
269 if ( val=="stdout" ) {
270 CoreDumpSvcHandler::ostr = &std::cout;
271 }
272 else if ( val=="stderr" ) {
273 CoreDumpSvcHandler::ostr = &std::cerr;
274 }
275 else {
276 ATH_MSG_WARNING("'" << val << "' not valid for " << m_coreDumpStream.name()
277 << ": " << m_coreDumpStream.documentation());
278 }
279 } else if ( p.name() == m_fatalHandlerFlags.name() ) {
280 if (m_fatalHandlerFlags.fromString(p.toString()).isSuccess()) {
281 if (m_fatalHandlerFlags != 0) {
282 Athena::Signal::handleFatal(nullptr, IOFD_INVALID, nullptr, nullptr, m_fatalHandlerFlags);
283 }
284 } else {
285 ATH_MSG_INFO("could not convert [" << p.toString() << "] to integer");
286 }
287 }
288 else if (p.name() == m_killOnSigInt.name()) {
289 if (m_killOnSigInt.fromString(p.toString()).isSuccess()) {
290 if (m_killOnSigInt) {
291 ATH_MSG_DEBUG("Will kill job on SIGINT (Ctrl-C)");
292 Athena::Signal::handle( SIGINT, ExitOnInt );
293 }
294 }
295 else {
296 ATH_MSG_WARNING("Could not convert [" << p.toString() << "] to bool");
297 }
298 }
299
300}
301
302//================================================================================
303// IService implementation
304//================================================================================
305StatusCode CoreDumpSvc::initialize()
306{
307 if (m_fatalHandlerFlags != 0) {
308 ATH_MSG_INFO("install f-a-t-a-l handler... (flag = " << m_fatalHandlerFlags.value() << ")");
309 Athena::Signal::handleFatal(nullptr, IOFD_INVALID, nullptr, nullptr, m_fatalHandlerFlags);
310 }
311
312 if (m_killOnSigInt) {
313 ATH_MSG_DEBUG("Will kill job on SIGINT (Ctrl-C)");
314 Athena::Signal::handle( SIGINT, ExitOnInt );
315 }
316
317 if ( installSignalHandler().isFailure() ) {
318 ATH_MSG_ERROR ("Could not install signal handlers");
319 return StatusCode::FAILURE;
320 }
321
322 // Register incident handler
323 ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", name());
324 if ( !incSvc.retrieve().isSuccess() ) {
325 ATH_MSG_WARNING ("Unable to retrieve the IncidentSvc");
326 }
327 else {
328 incSvc->addListener(this, IncidentType::BeginRun);
329 incSvc->addListener(this, IncidentType::BeginEvent);
330 incSvc->addListener(this, IncidentType::EndRun);
331 incSvc->addListener(this, IncidentType::EndEvent);
332 incSvc->addListener(this,"StoreCleared");
333 }
334
335 return StatusCode::SUCCESS;
336}
337
339{
340 auto numSlots = std::max<size_t>(1, Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents());
341 m_usrCoreDumps.resize(numSlots);
342 m_sysCoreDumps.resize(numSlots);
343 return StatusCode::SUCCESS;
344}
345
346StatusCode CoreDumpSvc::finalize()
347{
348 ATH_MSG_DEBUG ("Finalizing " << name());
349
350 if ( uninstallSignalHandler().isFailure() ) {
351 ATH_MSG_WARNING ("Could not uninstall signal handlers");
352 return StatusCode::FAILURE;
353 }
354
355 return StatusCode::SUCCESS;
356}
357
358//================================================================================
359// ICoreDumpSvc implementation
360//================================================================================
361
362//----------------------------------------------------------------------
363// Set a name/value pair in the core dump record
364//----------------------------------------------------------------------
365void CoreDumpSvc::setCoreDumpInfo( const std::string& name, const std::string& value )
366{
367 setCoreDumpInfo(Gaudi::Hive::currentContext(), name, value);
368}
369
370void CoreDumpSvc::setCoreDumpInfo( const EventContext& ctx, const std::string& name, const std::string& value )
371{
372 auto slot = ctx.valid() ? ctx.slot() : 0;
373 m_usrCoreDumps.at(slot)[name] = value;
374}
375
376//----------------------------------------------------------------------
377// Print all core dump records
378//----------------------------------------------------------------------
379void CoreDumpSvc::print ATLAS_NOT_THREAD_SAFE ()
380{
381 // Print a FATAL message but don't use the MsgStream anymore once we crashed
382 CoreDumpSvcHandler::log() << name() << " FATAL Caught fatal signal. Printing details to "
383 << m_coreDumpStream.value()
384 << (m_dumpCoreFile ? ". Will try to produce a core dump file on exit." : ".")
385 << std::endl;
386
387 CoreDumpSvcHandler::log() << dump() << std::flush;
388}
389
390//----------------------------------------------------------------------
391// Print all core dump records
392//----------------------------------------------------------------------
393std::string CoreDumpSvc::dump() const
394{
395 std::ostringstream os;
396 char buf[26];
397 const time_t now = time(nullptr);
398
399 os << "-------------------------------------------------------------------------------------" << "\n";
400 os << "Core dump from " << name() << " on " << System::hostName()
401 << " at " << ctime_r(&now, buf) /*<< "\n"*/; // ctime adds "\n"
402 os << "\n";
403
404 // Print additional information if available
405 if (m_siginfo) {
406 int signo = m_siginfo->si_signo; // shorthand
407
408 os << "Caught signal " << signo
409 << "(" << strsignal(signo) << "). Details: "
410 << "\n";
411
412 os << " errno = " << m_siginfo->si_errno
413 << ", code = " << m_siginfo->si_code
414 << " (" << Athena::Signal::describe(signo, m_siginfo->si_code) << ")"
415 << "\n";
416
417 os << " pid = " << m_siginfo->si_pid
418 << ", uid = " << m_siginfo->si_uid
419 << "\n";
420
421#ifndef __APPLE__
422 // These are set if the POSIX signal sender passed them.
423 os << " value = (" << m_siginfo->si_int << ", "
424 << std::hex << m_siginfo->si_ptr << ")" << std::dec << "\n";
425#endif
426
427 // memory usage informations
429
430 const long pagesz = sysconf(_SC_PAGESIZE);
431 os << " vmem = " << s.vm_pages*pagesz/1024./1024. << " MB\n"
432 << " rss = " << s.rss_pages*pagesz/1024./1024. << " MB\n";
433
434#ifndef __APPLE__
435 // more memory usage informations (system wide stuff)
436 // see sysinfo(2)
437
438 {
439 struct sysinfo sys;
440 if ( 0 == sysinfo(&sys) ) {
441 // all sizes are reported in sys.mem_unit bytes
442 const float mem_units = sys.mem_unit/(1024.*1024.);
443 os << " total-ram = " << sys.totalram * mem_units << " MB\n"
444 << " free-ram = " << sys.freeram * mem_units << " MB\n"
445 << " buffer-ram= " << sys.bufferram* mem_units << " MB\n"
446 << " total-swap= " << sys.totalswap* mem_units << " MB\n"
447 << " free-swap = " << sys.freeswap * mem_units << " MB\n";
448 }
449 }
450#endif
451
452 // This is the interesting address for memory faults.
453 if (signo == SIGILL || signo == SIGFPE || signo == SIGSEGV || signo == SIGBUS)
454 os << " addr = " << std::hex << m_siginfo->si_addr << std::dec << "\n";
455
456 os << "\n";
457 }
458
459 os << "Event counter: " << m_eventCounter << "\n";
460
461 SmartIF<IAlgManager> algMgr{serviceLocator()->as<IAlgManager>()};
462 SmartIF<IAlgContextSvc> algContextSvc;
463
464
465 // For serial, retrieve AlgContextSvc
466 if (Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents() == 0) {
467 algContextSvc = service("AlgContextSvc", /*createIf=*/ false);
468 }
469
470 // Loop over all slots
471 for (size_t t=0; t < m_sysCoreDumps.size(); ++t){
472
473 // Currently executing algorithm(s)
474 std::string currentAlg;
475
476 // Use AlgExecStateSvc in MT, otherwise AlgContextSvc
477 if (Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents() > 0) {
478 const EventContext ctx(0,t);
479 ATH_MSG_DEBUG("Using AlgExecStateSvc to determine current algorithm(s)");
480 try {
481 for (const IAlgorithm* alg : algMgr->getAlgorithms()) {
482 auto aes = alg->execState(ctx);
483 if (aes.state()==AlgExecState::State::Executing)
484 currentAlg += (alg->name() + " ");
485 }
486 }
487 catch (const GaudiException&) { // can happen if we get called before any algo execution
488 ATH_MSG_INFO("No information from AlgExecStateSvc because no algorithm was executed yet.");
489 }
490 }
491 else if (algContextSvc) {
492 ATH_MSG_DEBUG("Using AlgContextSvc to determine current algorithm");
493 IAlgorithm* alg = algContextSvc->currentAlg();
494 if (alg) currentAlg = alg->name();
495 }
496 else {
497 ATH_MSG_WARNING("AlgExecStateSvc or AlgContextSvc not available. Cannot determine current algorithm.");
498 }
499
500 if (currentAlg.empty()) currentAlg = "<NONE>";
501 os << "Slot " << std::setw(3) << t << " : Current algorithm = " << currentAlg << std::endl;
502
503 // System core dump
504 auto &sys = m_sysCoreDumps.at(t);
505 if (!sys.LastInc.empty()) {
506 os << " : Last Incident = " << sys.LastInc << std::endl
507 << " : Event ID = " << sys.EvId << std::endl;
508 }
509
510 // User core dump
511 auto &usr = m_usrCoreDumps.at(t);
512 if (!usr.empty()) {
513 for (auto &s : usr) {
514 os << " : (usr) " << s.first << " = " << s.second << std::endl;
515 }
516 }
517 }
518
519 if (algContextSvc) {
520 os << "Algorithm stack: ";
521 if ( algContextSvc->algorithms().empty() ) os << "<EMPTY>" << "\n";
522 else {
523 os << "\n";
524 for (auto alg : algContextSvc->algorithms()) {
525 if (alg) os << " " << alg->name() << "\n";
526 }
527 }
528 }
529
530 os << horizLine;
531 os << "| AtlasBaseDir : " << std::setw(66) << getenv("AtlasBaseDir") << " |\n";
532 os << "| AtlasVersion : " << std::setw(66) << getenv("AtlasVersion") << " |\n";
533 os << "| BINARY_TAG : " << std::setw(66) << getenv("BINARY_TAG") << " |\n";
534 os << horizLine;
535 os << " Note: to see line numbers in below stacktrace you might consider running following :\n";
536 os << " atlasAddress2Line --file <logfile>\n";
537
538 SmartIF<IAthenaSummarySvc> iass{service("AthenaSummarySvc", /*createIf*/false)};
539 if (iass) {
540 iass->addSummary("CoreDumpSvc",os.str());
541 iass->setStatus(1);
542 iass->createSummary().ignore();
543 }
544
545 return os.str();
546}
547
548//================================================================================
549// IIncidentHandler implementation
550//================================================================================
551
552void CoreDumpSvc::handle(const Incident& incident)
553{
554 //handle is single threaded in context;
555 auto slot = incident.context().valid() ? incident.context().slot() : 0;
556 auto &currRec = m_sysCoreDumps.at(slot);
557
558 currRec.LastInc = incident.source() + ":" + incident.type();
559
560 std::ostringstream oss;
561 oss << incident.context().eventID();
562 currRec.EvId = oss.str();
563
564 if (incident.type()==IncidentType::BeginEvent) {
565 // Set up an alternate stack for this thread, if not already done.
566 setAltStack();
568 } else if (incident.type() == "StoreCleared") {
569 // Try to force reallocation.
570 auto newstr = currRec.EvId;
571 // Intentional:
572 // cppcheck-suppress selfAssignment
573 newstr[0] = newstr[0];
574 currRec.EvId = std::move(newstr);
575 }
576
577}
578
579//================================================================================
580// Helpers for signal handler
581//================================================================================
582
583//----------------------------------------------------------------------
584// Install signal handler
585//----------------------------------------------------------------------
586StatusCode CoreDumpSvc::installSignalHandler ATLAS_NOT_THREAD_SAFE ()
587{
588 ATH_MSG_DEBUG ("Installing signal handler");
589 std::ostringstream oss;
590
591 for (auto sig : m_signals) {
592#ifndef __APPLE__
593 if (sig<1 || sig>SIGRTMAX) {
594 ATH_MSG_WARNING ("Invalid signal number " << sig << ". Ignoring.");
595 continue;
596 }
597#endif
598 oss << sig << "(" << strsignal(sig) << ") ";
599
600 // Set up an alternate stack for this thread.
601 setAltStack();
602
603 // Install new signal handler and backup old one
604 struct sigaction sigact;
605 memset (&sigact, 0, sizeof(sigact));
606 sigact.sa_sigaction = CoreDumpSvcHandler::action;
607 sigemptyset(&sigact.sa_mask);
608 sigact.sa_flags = SA_SIGINFO + SA_ONSTACK;
609 int ret = sigaction(sig, &sigact, &(CoreDumpSvcHandler::oldSigHandler[sig]));
610 if ( ret!=0 ) {
611 ATH_MSG_ERROR ("Error on installing handler for signal " << sig
612 << ": " << strerror(errno));
613 return StatusCode::FAILURE;
614 }
615 }
616 ATH_MSG_INFO ("Handling signals: " << oss.str());
617
618 return StatusCode::SUCCESS;
619}
620
621//----------------------------------------------------------------------
622// Uninstall signal handler
623//----------------------------------------------------------------------
624StatusCode CoreDumpSvc::uninstallSignalHandler ATLAS_NOT_THREAD_SAFE ()
625{
626 ATH_MSG_DEBUG ("Uninstalling signal handler");
627
628 StatusCode sc = StatusCode::SUCCESS;
629
630 for (const auto& kv : CoreDumpSvcHandler::oldSigHandler) {
631 int ret = sigaction(kv.first, &(kv.second), nullptr);
632 if ( ret!=0 ) {
633 sc = StatusCode::FAILURE;
634 ATH_MSG_WARNING("Error on uninstalling handler for signal " << kv.first
635 << ": " << strerror(errno));
636 }
637 }
638 return sc;
639}
640
641
642// Set an alternate stack to use for doing stack traces, so that we
643// can continue even if our primary stack is corrupt / exhausted.
644// Reserve 2MB on top of the minimum required for a signal handler.
645// This sets the alternate stack for the current thread, if it hasn't
646// already been done.
648{
649 std::vector<uint8_t>& stack = s_stack;
650 if (stack.empty()) {
651 stack.resize (std::max (SIGSTKSZ, MINSIGSTKSZ) + 2*1024*1024);
652 stack_t ss;
653 ss.ss_sp = stack.data();
654 ss.ss_flags = 0;
655 ss.ss_size = stack.size();
656 int ret = sigaltstack (&ss, nullptr);
657 if ( ret!=0 ) {
658 ATH_MSG_WARNING("Error on setting alternative stack! ");
659 }
660 }
661}
662
663
664thread_local std::vector<uint8_t> CoreDumpSvc::s_stack;
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
void CoreDumpSvc::print ATLAS_NOT_THREAD_SAFE()
Install fatal handler with default options.
static Double_t ss
static Double_t sc
Collecting a few shared bits and pieces from SEAL headers.
#define IOFD_INVALID
Invalid channel descriptor constant.
Definition SealCommon.h:20
This are the SEAL debug aids, adapted to build in Atlas, after the drop of that project.
This is the signal handler from SEAL, adapted to build in Atlas, after the drop of that project.
#define sigemptyset(x)
Definition SealSignal.h:82
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
static IOFD stacktraceFd(IOFD fd=IOFD_INVALID)
Set and return the file descriptor for stack trace output.
static const int FATAL_DUMP_CONTEXT
Option to make fataldump(int, siginfo_t *, void *) (invoked by fatal(int, siginfo_t *,...
Definition SealSignal.h:138
static const char * describe(int sig, int code)
Return the description for signal info code code for signal number sig.
static void revert(int sig)
Revert the signal number sig back to its default behaviour.
static const int FATAL_DUMP_SIG
Option to make fataldump(int, siginfo_t *, void *) (invoked by fatal(int, siginfo_t *,...
Definition SealSignal.h:126
static HandlerType handle(int sig, HandlerType handler, const sigset_t *blockMask=0)
Install a new signal handler handler for signal number sig and returns the old handler.
static const int FATAL_DUMP_STACK
Option to make fataldump(int, siginfo_t *, void *) (invoked by fatal(int, siginfo_t *,...
Definition SealSignal.h:130
Service to print additional information before a crash.
Definition CoreDumpSvc.h:43
siginfo_t * m_siginfo
Pointer to siginfo_t struct (set by signal handler)
Definition CoreDumpSvc.h:91
void setAltStack()
Set up an alternate stack for the current thread.
virtual StatusCode start() override
Gaudi::Property< int > m_fatalHandlerFlags
std::vector< UserCore_t > m_usrCoreDumps
User defined core dump info.
Definition CoreDumpSvc.h:89
static thread_local std::vector< uint8_t > s_stack
Definition CoreDumpSvc.h:94
Gaudi::Property< bool > m_callOldHandler
Gaudi::Property< bool > m_stackTrace
virtual std::string dump() const override
Print all core dump records.
virtual void handle(const Incident &incident) override
Incident listener.
virtual ~CoreDumpSvc() ATLAS_CTORDTOR_NOT_THREAD_SAFE
Destructor.
virtual void setCoreDumpInfo(const std::string &name, const std::string &value) override
Set a name/value pair in the core dump record.
Gaudi::Property< bool > m_dumpCoreFile
Gaudi::Property< bool > m_killOnSigInt
CoreDumpSvc()
Default constructor (do not use)
Gaudi::Property< std::string > m_coreDumpStream
std::vector< sysDumpRec > m_sysCoreDumps
Core dump info collected by this service.
Definition CoreDumpSvc.h:90
std::atomic< EventID::event_number_t > m_eventCounter
Event counter.
Definition CoreDumpSvc.h:92
Gaudi::Property< bool > m_fastStackTrace
Signal handler for CoreDumpSvc.
CoreDumpSvc * coreDumpSvc(nullptr)
pointer to CoreDumpSvc
SigHandler_t oldSigHandler
old signal handlers
std::map< int, struct sigaction > SigHandler_t
std::ostream &log ATLAS_NOT_THREAD_SAFE()
convenience method for logging
bool dumpCoreFile(false)
dump core file on exit?
bool callOldHandler(true)
forward calls to old handlers?
bool stackTrace(false)
produce stack trace?
bool fastStackTrace(false)
produce fast stack trace using CxxUtils/Seal
-event-from-file
struct athena_statm read_athena_statm()
MsgStream & msg
Definition testRead.cxx:32