ATLAS Offline Software
Loading...
Searching...
No Matches
CoreDumpSvc Class Reference

Service to print additional information before a crash. More...

#include <CoreDumpSvc.h>

Inheritance diagram for CoreDumpSvc:
Collaboration diagram for CoreDumpSvc:

Classes

struct  sysDumpRec

Public Member Functions

 CoreDumpSvc (const std::string &name, ISvcLocator *pSvcLocator) ATLAS_CTORDTOR_NOT_THREAD_SAFE
 Constructor with parameters.
virtual ~CoreDumpSvc () ATLAS_CTORDTOR_NOT_THREAD_SAFE
 Destructor.
ICoreDumpSvc implementation
virtual void setCoreDumpInfo (const std::string &name, const std::string &value) override
 Set a name/value pair in the core dump record.
virtual void setCoreDumpInfo (const EventContext &ctx, const std::string &name, const std::string &value) override
 Set a name/value pair in the core dump record for given EventContext.
virtual std::string dump () const override
 Print all core dump records.

Protected Member Functions

 CoreDumpSvc ()
 Default constructor (do not use).

Private Member Functions

void propertyHandler ATLAS_NOT_THREAD_SAFE (Gaudi::Details::PropertyBase &p)
 Property handler.
void print ATLAS_NOT_THREAD_SAFE ()
 Print core dump records to configured stream.
void setSigInfo (siginfo_t *info)
 Set pointer to siginfo_t struct.
StatusCode installSignalHandler ATLAS_NOT_THREAD_SAFE ()
 Install signal handlers.
StatusCode uninstallSignalHandler ATLAS_NOT_THREAD_SAFE ()
 Uninstall signal handlers.
void setAltStack ()
 Set up an alternate stack for the current thread.

Friends

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

Gaudi implementation

typedef tbb::concurrent_unordered_map< std::string, std::string > UserCore_t
std::vector< UserCore_t > m_usrCoreDumps
 User defined core dump info.
std::vector< sysDumpRec > m_sysCoreDumps
 Core dump info collected by this service.
siginfo_t * m_siginfo {nullptr}
 Pointer to siginfo_t struct (set by signal handler).
std::atomic< EventID::event_number_t > m_eventCounter {0}
 Event counter.
Gaudi::Property< std::vector< int > > m_signals
 Alternate stack for signal handler.
Gaudi::Property< bool > m_callOldHandler
Gaudi::Property< bool > m_dumpCoreFile
Gaudi::Property< bool > m_stackTrace
Gaudi::Property< bool > m_fastStackTrace
Gaudi::Property< std::string > m_coreDumpStream
Gaudi::Property< int > m_fatalHandlerFlags
Gaudi::Property< double > m_timeout
Gaudi::Property< bool > m_killOnSigInt {this, "KillOnSigInt",true, "Terminate job on SIGINT (aka Ctrl-C)"}
static std::vector< uint8_t > s_stack
virtual StatusCode initialize ATLAS_NOT_THREAD_SAFE () override
virtual StatusCode start () override
virtual StatusCode finalize ATLAS_NOT_THREAD_SAFE () override
virtual void handle (const Incident &incident) override
 Incident listener.

Detailed Description

Service to print additional information before a crash.

Author
Frank Winklmeier
Sami Kama

This service will catch fatal signals and print its internal core dump record. The service collects some information during event processing. Additional information can be added via setCoreDumpInfo().

For a list of job option properties see CoreDumpSvc::CoreDumpSvc().

Definition at line 41 of file CoreDumpSvc.h.

Member Typedef Documentation

◆ UserCore_t

typedef tbb::concurrent_unordered_map<std::string,std::string > CoreDumpSvc::UserCore_t
private

Definition at line 88 of file CoreDumpSvc.h.

Constructor & Destructor Documentation

◆ CoreDumpSvc() [1/2]

CoreDumpSvc::CoreDumpSvc ( )
protected

Default constructor (do not use).

◆ CoreDumpSvc() [2/2]

CoreDumpSvc::CoreDumpSvc ( const std::string & name,
ISvcLocator * pSvcLocator )

Constructor with parameters.

Definition at line 240 of file CoreDumpSvc.cxx.

240 :
241 base_class( name, pSvcLocator )
242{
243 // Set us as the current instance
245
246 m_callOldHandler.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
247 m_dumpCoreFile.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
248 m_stackTrace.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
249 m_fastStackTrace.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
250 m_coreDumpStream.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
251 m_fatalHandlerFlags.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
252 m_killOnSigInt.declareUpdateHandler(&CoreDumpSvc::propertyHandler, this);
253 // Allocate for 2 slots just for now.
254 m_usrCoreDumps.resize(2);
255 m_sysCoreDumps.resize(2);
256}
Gaudi::Property< int > m_fatalHandlerFlags
std::vector< UserCore_t > m_usrCoreDumps
User defined core dump info.
Definition CoreDumpSvc.h:89
Gaudi::Property< bool > m_callOldHandler
Gaudi::Property< bool > m_stackTrace
Gaudi::Property< bool > m_dumpCoreFile
Gaudi::Property< bool > m_killOnSigInt
Gaudi::Property< std::string > m_coreDumpStream
std::vector< sysDumpRec > m_sysCoreDumps
Core dump info collected by this service.
Definition CoreDumpSvc.h:90
Gaudi::Property< bool > m_fastStackTrace
CoreDumpSvc * coreDumpSvc(nullptr)
pointer to CoreDumpSvc

◆ ~CoreDumpSvc()

CoreDumpSvc::~CoreDumpSvc ( )
virtual

Destructor.

Definition at line 258 of file CoreDumpSvc.cxx.

259{
261}

Member Function Documentation

◆ ATLAS_NOT_THREAD_SAFE() [1/6]

StatusCode uninstallSignalHandler CoreDumpSvc::ATLAS_NOT_THREAD_SAFE ( )
private

Uninstall signal handlers.

◆ ATLAS_NOT_THREAD_SAFE() [2/6]

StatusCode installSignalHandler CoreDumpSvc::ATLAS_NOT_THREAD_SAFE ( )
private

Install signal handlers.

◆ ATLAS_NOT_THREAD_SAFE() [3/6]

void print CoreDumpSvc::ATLAS_NOT_THREAD_SAFE ( )
private

Print core dump records to configured stream.

◆ ATLAS_NOT_THREAD_SAFE() [4/6]

virtual StatusCode finalize CoreDumpSvc::ATLAS_NOT_THREAD_SAFE ( )
overridevirtual

◆ ATLAS_NOT_THREAD_SAFE() [5/6]

virtual StatusCode initialize CoreDumpSvc::ATLAS_NOT_THREAD_SAFE ( )
overridevirtual

◆ ATLAS_NOT_THREAD_SAFE() [6/6]

void propertyHandler CoreDumpSvc::ATLAS_NOT_THREAD_SAFE ( Gaudi::Details::PropertyBase & p)
private

Property handler.

◆ dump()

std::string CoreDumpSvc::dump ( ) const
overridevirtual

Print all core dump records.

Definition at line 398 of file CoreDumpSvc.cxx.

399{
400 std::ostringstream os;
401 char buf[26];
402 const time_t now = time(nullptr);
403
404#define PR(FMT, ...) std::println(os, FMT __VA_OPT__(,) __VA_ARGS__)
405
406 PR("-------------------------------------------------------------------------------------");
407 std::print (os, "Core dump from {} on {} at {}",
408 name(), System::hostName(), ctime_r(&now, buf)); // ctime adds "\n"`
409 PR("");
410
411 // Print additional information if available
412 if (m_siginfo) {
413 int signo = m_siginfo->si_signo; // shorthand
414
415 PR ("Caught signal {}({}). Details: ", signo, strsignal(signo));
416
417 PR (" errno = {}, code = {} ({})",
418 m_siginfo->si_errno, m_siginfo->si_code, Athena::Signal::describe(signo, m_siginfo->si_code));
419
420 PR (" pid = {}, uid = {}", m_siginfo->si_pid, m_siginfo->si_uid);
421#ifndef __APPLE__
422 // These are set if the POSIX signal sender passed them.
423 PR (" value = ({}, {})", m_siginfo->si_int, m_siginfo->si_ptr);
424#endif
425
426 // memory usage informations
427 athena_statm s = read_athena_statm();
428
429 const long pagesz = sysconf(_SC_PAGESIZE);
430 PR (" vmem = {} MB\n"
431 " rss = {} MB",
432 s.vm_pages*pagesz/1024./1024., s.rss_pages*pagesz/1024./1024.);
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 PR (" total-ram = {} MB\n"
444 " free-ram = {} MB\n"
445 " buffer-ram= {} MB\n"
446 " total-swap= {} MB\n"
447 " free-swap = {} MB",
448 sys.totalram * mem_units,
449 sys.freeram * mem_units,
450 sys.bufferram* mem_units,
451 sys.totalswap* mem_units,
452 sys.freeswap * mem_units);
453 }
454 }
455#endif
456
457 // This is the interesting address for memory faults.
458 if (signo == SIGILL || signo == SIGFPE || signo == SIGSEGV || signo == SIGBUS)
459 PR (" addr = {}", m_siginfo->si_addr);
460
461 PR ("");
462 }
463
464 PR ( "Event counter: {}", m_eventCounter.load());
465
466 SmartIF<IAlgManager> algMgr{serviceLocator()->as<IAlgManager>()};
467 SmartIF<IAlgContextSvc> algContextSvc;
468
469
470 // For serial, retrieve AlgContextSvc
471 if (Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents() == 0) {
472 algContextSvc = service("AlgContextSvc", /*createIf=*/ false);
473 }
474
475 // Loop over all slots
476 for (size_t t=0; t < m_sysCoreDumps.size(); ++t){
477
478 // Currently executing algorithm(s)
479 std::string currentAlg;
480
481 // Use AlgExecStateSvc in MT, otherwise AlgContextSvc
482 if (Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents() > 0) {
483 const EventContext ctx(0,t);
484 ATH_MSG_DEBUG("Using AlgExecStateSvc to determine current algorithm(s)");
485 try {
486 for (const IAlgorithm* alg : algMgr->getAlgorithms()) {
487 auto aes = alg->execState(ctx);
488 if (aes.state()==AlgExecState::State::Executing)
489 currentAlg += (alg->name() + " ");
490 }
491 }
492 catch (const GaudiException&) { // can happen if we get called before any algo execution
493 ATH_MSG_INFO("No information from AlgExecStateSvc because no algorithm was executed yet.");
494 }
495 }
496 else if (algContextSvc) {
497 ATH_MSG_DEBUG("Using AlgContextSvc to determine current algorithm");
498 IAlgorithm* alg = algContextSvc->currentAlg();
499 if (alg) currentAlg = alg->name();
500 }
501 else {
502 ATH_MSG_WARNING("AlgExecStateSvc or AlgContextSvc not available. Cannot determine current algorithm.");
503 }
504
505 if (currentAlg.empty()) currentAlg = "<NONE>";
506 PR ( "Slot {:3} : Current algorithm = {}", t, currentAlg);
507
508 // System core dump
509 auto &sys = m_sysCoreDumps.at(t);
510 if (!sys.LastInc.empty()) {
511 PR (" : Last Incident = {}\n"
512 " : Event ID = {}",
513 sys.LastInc, sys.EvId);
514 }
515
516 // User core dump
517 auto &usr = m_usrCoreDumps.at(t);
518 if (!usr.empty()) {
519 for (auto &s : usr) {
520 PR (" : (usr) {} = {}", s.first, s.second);
521 }
522 }
523 }
524
525 if (algContextSvc) {
526 std::print (os, "Algorithm stack: ");
527 if ( algContextSvc->algorithms().empty() )
528 PR ("<EMPTY>");
529 else {
530 PR ("");
531 for (auto alg : algContextSvc->algorithms()) {
532 if (alg) PR (" {}", alg->name());
533 }
534 }
535 }
536
537 PR ("{}"
538 "| AtlasBaseDir : {:66} |\n"
539 "| AtlasVersion : {:66} |\n"
540 "| BINARY_TAG : {:66} |\n"
541 "{}"
542 " Note: to see line numbers in below stacktrace you might consider running following :\n"
543 " atlasAddress2Line --file <logfile>",
544 horizLine,
545 getenv("AtlasBaseDir"),
546 getenv("AtlasVersion"),
547 getenv("BINARY_TAG"),
548 horizLine);
549
550 SmartIF<IAthenaSummarySvc> iass{service("AthenaSummarySvc", /*createIf*/false)};
551 if (iass) {
552 iass->addSummary("CoreDumpSvc",os.str());
553 iass->setStatus(1);
554 iass->createSummary().ignore();
555 }
556#undef PR
557
558 return os.str();
559}
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
#define PR(FMT,...)
static const char * describe(int sig, int code)
Return the description for signal info code code for signal number sig.
siginfo_t * m_siginfo
Pointer to siginfo_t struct (set by signal handler).
Definition CoreDumpSvc.h:91
std::atomic< EventID::event_number_t > m_eventCounter
Event counter.
Definition CoreDumpSvc.h:92
time(flags, cells_name, *args, **kw)
std::string getenv(const std::string &variableName)
get an environment variable
struct athena_statm read_athena_statm()

◆ handle()

void CoreDumpSvc::handle ( const Incident & incident)
overridevirtual

Incident listener.

Definition at line 565 of file CoreDumpSvc.cxx.

566{
567 //handle is single threaded in context;
568 auto slot = incident.context().valid() ? incident.context().slot() : 0;
569 auto &currRec = m_sysCoreDumps.at(slot);
570
571 currRec.LastInc = incident.source() + ":" + incident.type();
572
573 std::ostringstream oss;
574 oss << incident.context().eventID();
575 currRec.EvId = oss.str();
576
577 if (incident.type()==IncidentType::BeginEvent) {
578 // Set up an alternate stack for this thread, if not already done.
579 setAltStack();
581 } else if (incident.type() == "StoreCleared") {
582 // Try to force reallocation.
583 auto newstr = currRec.EvId;
584 // Intentional:
585 // cppcheck-suppress selfAssignment
586 newstr[0] = newstr[0];
587 currRec.EvId = std::move(newstr);
588 }
589
590}
void setAltStack()
Set up an alternate stack for the current thread.

◆ setAltStack()

void CoreDumpSvc::setAltStack ( )
private

Set up an alternate stack for the current thread.

Definition at line 660 of file CoreDumpSvc.cxx.

661{
662 std::vector<uint8_t>& stack = s_stack;
663 if (stack.empty()) {
664 stack.resize (std::max (SIGSTKSZ, MINSIGSTKSZ) + 2*1024*1024);
665 stack_t ss;
666 ss.ss_sp = stack.data();
667 ss.ss_flags = 0;
668 ss.ss_size = stack.size();
669 int ret = sigaltstack (&ss, nullptr);
670 if ( ret!=0 ) {
671 ATH_MSG_WARNING("Error on setting alternative stack! ");
672 }
673 }
674}
static Double_t ss
static std::vector< uint8_t > s_stack
Definition CoreDumpSvc.h:94

◆ setCoreDumpInfo() [1/2]

void CoreDumpSvc::setCoreDumpInfo ( const EventContext & ctx,
const std::string & name,
const std::string & value )
overridevirtual

Set a name/value pair in the core dump record for given EventContext.

Definition at line 375 of file CoreDumpSvc.cxx.

376{
377 auto slot = ctx.valid() ? ctx.slot() : 0;
378 m_usrCoreDumps.at(slot)[name] = value;
379}

◆ setCoreDumpInfo() [2/2]

void CoreDumpSvc::setCoreDumpInfo ( const std::string & name,
const std::string & value )
overridevirtual

Set a name/value pair in the core dump record.

Definition at line 370 of file CoreDumpSvc.cxx.

371{
372 setCoreDumpInfo(Gaudi::Hive::currentContext(), name, value);
373}
virtual void setCoreDumpInfo(const std::string &name, const std::string &value) override
Set a name/value pair in the core dump record.

◆ setSigInfo()

void CoreDumpSvc::setSigInfo ( siginfo_t * info)
inlineprivate

Set pointer to siginfo_t struct.

Definition at line 136 of file CoreDumpSvc.h.

◆ start()

StatusCode CoreDumpSvc::start ( )
overridevirtual

Definition at line 343 of file CoreDumpSvc.cxx.

344{
345 auto numSlots = std::max<size_t>(1, Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents());
346 m_usrCoreDumps.resize(numSlots);
347 m_sysCoreDumps.resize(numSlots);
348 return StatusCode::SUCCESS;
349}

◆ CoreDumpSvcHandler::action

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

Member Data Documentation

◆ m_callOldHandler

Gaudi::Property<bool> CoreDumpSvc::m_callOldHandler
private
Initial value:
{this, "CallOldHandler", true,
"Call previous signal handler"}

Definition at line 101 of file CoreDumpSvc.h.

101 {this, "CallOldHandler", true,
102 "Call previous signal handler"};

◆ m_coreDumpStream

Gaudi::Property<std::string> CoreDumpSvc::m_coreDumpStream
private
Initial value:
{this, "CoreDumpStream", "stdout",
"Stream to use for core dump [stdout,stderr]"}

Definition at line 113 of file CoreDumpSvc.h.

113 {this, "CoreDumpStream", "stdout",
114 "Stream to use for core dump [stdout,stderr]"};

◆ m_dumpCoreFile

Gaudi::Property<bool> CoreDumpSvc::m_dumpCoreFile
private
Initial value:
{this, "DumpCoreFile", false,
"Produce a core dump file if resource limits (ulimit -c) allow"}

Definition at line 104 of file CoreDumpSvc.h.

104 {this, "DumpCoreFile", false,
105 "Produce a core dump file if resource limits (ulimit -c) allow"};

◆ m_eventCounter

std::atomic<EventID::event_number_t> CoreDumpSvc::m_eventCounter {0}
private

Event counter.

Definition at line 92 of file CoreDumpSvc.h.

92{0};

◆ m_fastStackTrace

Gaudi::Property<bool> CoreDumpSvc::m_fastStackTrace
private
Initial value:
{this, "FastStackTrace", false,
"Produce fast stack trace of current thread"}

Definition at line 110 of file CoreDumpSvc.h.

110 {this, "FastStackTrace", false,
111 "Produce fast stack trace of current thread"};

◆ m_fatalHandlerFlags

Gaudi::Property<int> CoreDumpSvc::m_fatalHandlerFlags
private
Initial value:
{this, "FatalHandler", 0,
"Flags given to the fatal handler this service installs\n"
"if the flag is zero, no additional fatal handler is installed."}

Definition at line 116 of file CoreDumpSvc.h.

116 {this, "FatalHandler", 0,
117 "Flags given to the fatal handler this service installs\n"
118 "if the flag is zero, no additional fatal handler is installed."};

◆ m_killOnSigInt

Gaudi::Property<bool> CoreDumpSvc::m_killOnSigInt {this, "KillOnSigInt",true, "Terminate job on SIGINT (aka Ctrl-C)"}
private

Definition at line 124 of file CoreDumpSvc.h.

124{this, "KillOnSigInt",true, "Terminate job on SIGINT (aka Ctrl-C)"};

◆ m_siginfo

siginfo_t* CoreDumpSvc::m_siginfo {nullptr}
private

Pointer to siginfo_t struct (set by signal handler).

Definition at line 91 of file CoreDumpSvc.h.

91{nullptr};

◆ m_signals

Gaudi::Property<std::vector<int> > CoreDumpSvc::m_signals
private
Initial value:
{this, "Signals", {SIGSEGV,SIGBUS,SIGILL,SIGABRT,SIGFPE,SIGALRM},
"List of signals to catch"}

Alternate stack for signal handler.

Properties

Definition at line 98 of file CoreDumpSvc.h.

98 {this, "Signals", {SIGSEGV,SIGBUS,SIGILL,SIGABRT,SIGFPE,SIGALRM},
99 "List of signals to catch"};

◆ m_stackTrace

Gaudi::Property<bool> CoreDumpSvc::m_stackTrace
private
Initial value:
{this, "StackTrace", false,
"Produce (gdb) stack trace on crash. Useful if no other signal handler is used"}

Definition at line 107 of file CoreDumpSvc.h.

107 {this, "StackTrace", false,
108 "Produce (gdb) stack trace on crash. Useful if no other signal handler is used"};

◆ m_sysCoreDumps

std::vector<sysDumpRec> CoreDumpSvc::m_sysCoreDumps
private

Core dump info collected by this service.

Definition at line 90 of file CoreDumpSvc.h.

◆ m_timeout

Gaudi::Property<double> CoreDumpSvc::m_timeout
private
Initial value:
{this, "TimeOut", 30.0*60*1e9,
"Terminate job after it this reaches the time out in Wallclock time, "
"usually due to hanging during stack unwinding. Timeout given in nanoseconds despite seconds precision"}

Definition at line 120 of file CoreDumpSvc.h.

120 {this, "TimeOut", 30.0*60*1e9,
121 "Terminate job after it this reaches the time out in Wallclock time, "
122 "usually due to hanging during stack unwinding. Timeout given in nanoseconds despite seconds precision"};

◆ m_usrCoreDumps

std::vector<UserCore_t> CoreDumpSvc::m_usrCoreDumps
private

User defined core dump info.

Definition at line 89 of file CoreDumpSvc.h.

◆ s_stack

std::vector< uint8_t > CoreDumpSvc::s_stack
thread_localstaticprivate

Definition at line 94 of file CoreDumpSvc.h.


The documentation for this class was generated from the following files: