ATLAS Offline Software
Loading...
Searching...
No Matches
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?
bool dumpCoreFile (false)
 dump core file on exit?
bool stackTrace (false)
 produce stack trace?
bool fastStackTrace (false)
 produce fast stack trace using CxxUtils/Seal
CoreDumpSvc * coreDumpSvc (nullptr)
 pointer to CoreDumpSvc
std::ostream &log ATLAS_NOT_THREAD_SAFE ()
 convenience method for logging
void action ATLAS_NOT_THREAD_SAFE (int sig, siginfo_t *info, void *extra)
 Signal handler for the CoreDumpSvc.

Variables

SigHandler_t oldSigHandler
 old signal handlers

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 81 of file CoreDumpSvc.cxx.

Function Documentation

◆ ATLAS_NOT_THREAD_SAFE() [1/2]

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

convenience method for logging

Definition at line 91 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 96 of file CoreDumpSvc.cxx.

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 }
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
#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 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 const int FATAL_DUMP_STACK
Option to make fataldump(int, siginfo_t *, void *) (invoked by fatal(int, siginfo_t *,...
Definition SealSignal.h:130
CoreDumpSvc * coreDumpSvc(nullptr)
pointer to CoreDumpSvc
SigHandler_t oldSigHandler
old signal handlers
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
float round(const float toRound, const unsigned int decimals)
Definition Mdt.cxx:27
MsgStream & msg
Definition testRead.cxx:32

◆ 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 83 of file CoreDumpSvc.cxx.