ATLAS Offline Software
Loading...
Searching...
No Matches
CoreDumpSvc.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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#include <print>
28
29// Package includes
30#include "CoreDumpSvc.h"
31
32// ROOT includes
33#include "TSystem.h"
34
35// Gaudi includes
36#include "Gaudi/Property.h"
37#include "GaudiKernel/IAlgorithm.h"
38#include "GaudiKernel/IIncidentSvc.h"
39#include "GaudiKernel/IAlgContextSvc.h"
40#include "GaudiKernel/IAlgExecStateSvc.h"
41#include "GaudiKernel/IAlgManager.h"
42#include "GaudiKernel/ServiceHandle.h"
43#include "GaudiKernel/System.h"
44#include "GaudiKernel/ConcurrencyFlags.h"
45#include "GaudiKernel/EventContext.h"
46
47// Athena includes
50#include "CxxUtils/SealCommon.h"
51#include "CxxUtils/SealSignal.h"
52#include "CxxUtils/SealDebug.h"
55
56namespace {
57
58 const char* const horizLine = "-------------------------------------------------------------------------------------\n";
59
60 void ExitOnInt( int sig, siginfo_t*, void* ) {
61 if ( sig == SIGINT ) {
62 // called on user ^C
63 std::println();
64 std::println (std::cerr, "Athena CRITICAL stopped by user interrupt");
65 raise(SIGKILL);
66 }
67 }
68
69} // unnamed namespace
70
71
80{
81 typedef std::map<int, struct sigaction> SigHandler_t;
82
84 bool callOldHandler(true);
85 bool dumpCoreFile(false);
86 bool stackTrace(false);
87 bool fastStackTrace(false);
89 std::ostream* ostr(&std::cout);
90
91 std::ostream& log ATLAS_NOT_THREAD_SAFE () { return *ostr; }
92
96 void action ATLAS_NOT_THREAD_SAFE ( int sig, siginfo_t *info, void* extra )
97 {
98 // Careful: don't do anything here that might allocate memory.
99
100 // Protect against recursion.
101 // We originally used a thread_local here --- but accessing
102 // a thread_local can result in a call to malloc.
103
104 const int maxcalls = 64;
105 static std::atomic<int> ncalls (0);
106 if (++ncalls >= maxcalls) _exit (98);
107
108 static std::mutex tidlist_mutex;
109 static size_t ntids ATLAS_THREAD_SAFE = 0;
110 static pthread_t tids[maxcalls] ATLAS_THREAD_SAFE;
111 {
112 pthread_t self = pthread_self();
113 std::lock_guard<std::mutex> lock (tidlist_mutex);
114 for (size_t i = 0; i < ntids; i++) {
115 if (pthread_equal (self, tids[i])) return;
116 }
117 if (ntids == maxcalls) _exit (98);
118 tids[ntids++] = self;
119 }
120
121 // Count the number of threads trying to dump.
122 static std::atomic<int> inThreads = 0;
123 ++inThreads;
124
125 const unsigned int timeoutSeconds = static_cast<unsigned int>(round(coreDumpSvc->m_timeout * 1e-9));
126
127 if ( sig == SIGALRM) {
128 if (dumpCoreFile) {
129 std::println (log(), "Received SIGALRM. Aborting job...");
130 // Restore default abort handler that should create a core file
131 Athena::Signal::revert (SIGABRT);
132 std::abort();
133 }
134 else {
135 std::println (log(), "Received SIGALRM. Terminating job...");
136 _exit(97); // exit without raising any further signals
137 }
138 }
139
140 // Only allow one thread past at a time.
141 // Try to assume as little as possible about the state of the library.
142 // We don't want to hang forever here, but we also don't want
143 // to call any library functions that might use signals under the hood.
144 // So use nanosleep() to do the delay --- that's defined to be
145 // independent of signals.
146 static std::mutex threadMutex;
147 const timespec one_second { 1, 0 };
148 {
149 unsigned int waits = 0;
150 while (!threadMutex.try_lock()) {
151 nanosleep (&one_second, nullptr);
152 if (++waits > timeoutSeconds) _exit (97);
153 }
154 }
155
156 // setup timeout
157 if ( timeoutSeconds > 0 && (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT) ) {
158 // This will trigger SIGALRM, which we then handle ourselves above
159 alarm(timeoutSeconds);
160 }
161
162 // Do fast stack trace before anything that might touch the heap.
163 // For extra paranoia, avoid iostreams/stdio and use write() directly.
164 if (fastStackTrace) {
165 write (1, horizLine, strlen(horizLine));
166 const char* msg = "Producing (fast) stack trace...\n";
167 write (1, msg, strlen (msg));
168 write (1, horizLine, strlen(horizLine));
169 Athena::Signal::fatalDump (sig, info, extra,
170 Athena::DebugAids::stacktraceFd(),
174 write (1, "\n", 1);
175 }
176
177 std::cout.flush();
178 std::cerr.flush();
179
180 if (coreDumpSvc) {
181 coreDumpSvc->setSigInfo(info);
182 coreDumpSvc->print();
183 }
184
185 if (gSystem && stackTrace) {
186 std::print (log(), "{}Producing stack trace (can be slow, check gdb process)...\n{}",
187 horizLine, horizLine);
188 log().flush();
189 gSystem->StackTrace();
190 std::println (log());
191 }
192
193 if (callOldHandler) {
194 // Call previous signal handler
195 // Need to distinguish between the two different types
196 const struct sigaction& oact = oldSigHandler[sig];
197 std::print (log(), "{}Invoking previous signal handler (can be slow, check gdb process)...\n{}",
198 horizLine, horizLine);
199 log().flush();
200 if ( oact.sa_flags & SA_SIGINFO ) {
201 oact.sa_sigaction(sig, info, extra);
202 }
203 else if (oact.sa_handler != SIG_DFL && oact.sa_handler != SIG_IGN ) {
204 oact.sa_handler(sig);
205 }
206 else {
207 std::println (log(), "Could not invoke previous signal handler");
208 }
209 }
210
211 // This thread is done dumping.
212 threadMutex.unlock();
213 --inThreads;
214
215 if (coreDumpSvc && (sig == SIGSEGV || sig == SIGBUS || sig == SIGABRT) ) {
216 // Don't terminate the program while there are other threads
217 // trying to dump (but don't wait forever either).
218 unsigned int waits = 0;
219 while (inThreads > 0 && waits < timeoutSeconds) {
220 nanosleep (&one_second, nullptr);
221 }
222
223 if (dumpCoreFile) {
224 std::println (log(), "Aborting job... ");
225 // Restore default abort handler that should create a core file
226 Athena::Signal::revert (SIGABRT);
227 std::abort();
228 }
229
230 // Exit now on a fatal signal; otherwise, we can hang.
231 _exit (99);
232 }
233 }
234
235}
236
237//================================================================================
238// C'tor, D'tor, Property handler
239//================================================================================
240CoreDumpSvc::CoreDumpSvc( const std::string& name, ISvcLocator* pSvcLocator ) :
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}
257
262
263void CoreDumpSvc::propertyHandler(Gaudi::Details::PropertyBase& p)
264{
269
270 if ( p.name()==m_coreDumpStream.name() ) {
271 const std::string val = p.toString();
272 if ( val=="stdout" ) {
273 CoreDumpSvcHandler::ostr = &std::cout;
274 }
275 else if ( val=="stderr" ) {
276 CoreDumpSvcHandler::ostr = &std::cerr;
277 }
278 else {
279 ATH_MSG_WARNING("'{}' not valid for {}: {}",
280 val,
281 m_coreDumpStream.name(),
282 m_coreDumpStream.documentation());
283 }
284 } else if ( p.name() == m_fatalHandlerFlags.name() ) {
285 if (m_fatalHandlerFlags.fromString(p.toString()).isSuccess()) {
286 if (m_fatalHandlerFlags != 0) {
287 Athena::Signal::handleFatal(nullptr, IOFD_INVALID, nullptr, nullptr, m_fatalHandlerFlags);
288 }
289 } else {
290 ATH_MSG_INFO("could not convert [{}] to integer", p.toString());
291 }
292 }
293 else if (p.name() == m_killOnSigInt.name()) {
294 if (m_killOnSigInt.fromString(p.toString()).isSuccess()) {
295 if (m_killOnSigInt) {
296 ATH_MSG_DEBUG("Will kill job on SIGINT (Ctrl-C)");
297 Athena::Signal::handle( SIGINT, ExitOnInt );
298 }
299 }
300 else {
301 ATH_MSG_WARNING("Could not convert [{}] to bool", p.toString());
302 }
303 }
304
305}
306
307//================================================================================
308// IService implementation
309//================================================================================
310StatusCode CoreDumpSvc::initialize()
311{
312 if (m_fatalHandlerFlags != 0) {
313 ATH_MSG_INFO("install f-a-t-a-l handler... (flag = {})", m_fatalHandlerFlags.value());
314 Athena::Signal::handleFatal(nullptr, IOFD_INVALID, nullptr, nullptr, m_fatalHandlerFlags);
315 }
316
317 if (m_killOnSigInt) {
318 ATH_MSG_DEBUG("Will kill job on SIGINT (Ctrl-C)");
319 Athena::Signal::handle( SIGINT, ExitOnInt );
320 }
321
322 if ( installSignalHandler().isFailure() ) {
323 ATH_MSG_ERROR ("Could not install signal handlers");
324 return StatusCode::FAILURE;
325 }
326
327 // Register incident handler
328 ServiceHandle<IIncidentSvc> incSvc("IncidentSvc", name());
329 if ( !incSvc.retrieve().isSuccess() ) {
330 ATH_MSG_WARNING ("Unable to retrieve the IncidentSvc");
331 }
332 else {
333 incSvc->addListener(this, IncidentType::BeginRun);
334 incSvc->addListener(this, IncidentType::BeginEvent);
335 incSvc->addListener(this, IncidentType::EndRun);
336 incSvc->addListener(this, IncidentType::EndEvent);
337 incSvc->addListener(this,"StoreCleared");
338 }
339
340 return StatusCode::SUCCESS;
341}
342
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}
350
351StatusCode CoreDumpSvc::finalize()
352{
353 ATH_MSG_DEBUG ("Finalizing {}", name());
354
355 if ( uninstallSignalHandler().isFailure() ) {
356 ATH_MSG_WARNING ("Could not uninstall signal handlers");
357 return StatusCode::FAILURE;
358 }
359
360 return StatusCode::SUCCESS;
361}
362
363//================================================================================
364// ICoreDumpSvc implementation
365//================================================================================
366
367//----------------------------------------------------------------------
368// Set a name/value pair in the core dump record
369//----------------------------------------------------------------------
370void CoreDumpSvc::setCoreDumpInfo( const std::string& name, const std::string& value )
371{
372 setCoreDumpInfo(Gaudi::Hive::currentContext(), name, value);
373}
374
375void CoreDumpSvc::setCoreDumpInfo( const EventContext& ctx, const std::string& name, const std::string& value )
376{
377 auto slot = ctx.valid() ? ctx.slot() : 0;
378 m_usrCoreDumps.at(slot)[name] = value;
379}
380
381//----------------------------------------------------------------------
382// Print all core dump records
383//----------------------------------------------------------------------
384void CoreDumpSvc::print ATLAS_NOT_THREAD_SAFE ()
385{
386 // Print a FATAL message but don't use the MsgStream anymore once we crashed
387 std::println (CoreDumpSvcHandler::log(),
388 "{} FATAL Caught fatal signal. Printing details to {}{}",
389 name(), m_coreDumpStream.value(),
390 (m_dumpCoreFile ? ". Will try to produce a core dump file on exit." : "."));
391
392 CoreDumpSvcHandler::log() << dump() << std::flush;
393}
394
395//----------------------------------------------------------------------
396// Print all core dump records
397//----------------------------------------------------------------------
398std::string CoreDumpSvc::dump() const
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
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}
560
561//================================================================================
562// IIncidentHandler implementation
563//================================================================================
564
565void CoreDumpSvc::handle(const Incident& incident)
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}
591
592//================================================================================
593// Helpers for signal handler
594//================================================================================
595
596//----------------------------------------------------------------------
597// Install signal handler
598//----------------------------------------------------------------------
599StatusCode CoreDumpSvc::installSignalHandler ATLAS_NOT_THREAD_SAFE ()
600{
601 ATH_MSG_DEBUG ("Installing signal handler");
602 std::ostringstream oss;
603
604 for (auto sig : m_signals) {
605#ifndef __APPLE__
606 if (sig<1 || sig>SIGRTMAX) {
607 ATH_MSG_WARNING ("Invalid signal number {}. Ignoring.", sig);
608 continue;
609 }
610#endif
611 std::print (oss, "{}({}) ", sig, strsignal(sig));
612
613 // Set up an alternate stack for this thread.
614 setAltStack();
615
616 // Install new signal handler and backup old one
617 struct sigaction sigact;
618 memset (&sigact, 0, sizeof(sigact));
619 sigact.sa_sigaction = CoreDumpSvcHandler::action;
620 sigemptyset(&sigact.sa_mask);
621 sigact.sa_flags = SA_SIGINFO + SA_ONSTACK;
622 int ret = sigaction(sig, &sigact, &(CoreDumpSvcHandler::oldSigHandler[sig]));
623 if ( ret!=0 ) {
624 ATH_MSG_ERROR ("Error on installing handler for signal {}: {}",
625 sig, strerror(errno));
626 return StatusCode::FAILURE;
627 }
628 }
629 ATH_MSG_INFO ("Handling signals: {}", oss.str());
630
631 return StatusCode::SUCCESS;
632}
633
634//----------------------------------------------------------------------
635// Uninstall signal handler
636//----------------------------------------------------------------------
637StatusCode CoreDumpSvc::uninstallSignalHandler ATLAS_NOT_THREAD_SAFE ()
638{
639 ATH_MSG_DEBUG ("Uninstalling signal handler");
640
641 StatusCode sc = StatusCode::SUCCESS;
642
643 for (const auto& kv : CoreDumpSvcHandler::oldSigHandler) {
644 int ret = sigaction(kv.first, &(kv.second), nullptr);
645 if ( ret!=0 ) {
646 sc = StatusCode::FAILURE;
647 ATH_MSG_WARNING("Error on uninstalling handler for signal {}: {}",
648 kv.first, strerror(errno));
649 }
650 }
651 return sc;
652}
653
654
655// Set an alternate stack to use for doing stack traces, so that we
656// can continue even if our primary stack is corrupt / exhausted.
657// Reserve 2MB on top of the minimum required for a signal handler.
658// This sets the alternate stack for the current thread, if it hasn't
659// already been done.
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}
675
676
677thread_local std::vector<uint8_t> CoreDumpSvc::s_stack;
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
void CoreDumpSvc::print ATLAS_NOT_THREAD_SAFE()
Install fatal handler with default options.
#define PR(FMT,...)
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
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 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.
static std::vector< uint8_t > s_stack
Definition CoreDumpSvc.h:94
virtual StatusCode start() override
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
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
::StatusCode StatusCode
StatusCode definition for legacy code.
-event-from-file
struct athena_statm read_athena_statm()
MsgStream & msg
Definition testRead.cxx:32