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

#include <FPEAuditor.h>

Inheritance diagram for FPEAuditor:
Collaboration diagram for FPEAuditor:

Public Member Functions

 FPEAuditor (const std::string &name, ISvcLocator *pSvcLocator)
 Constructor.
virtual ~FPEAuditor ()
 Destructor.
virtual StatusCode initialize () override
 Gaudi hooks.
virtual StatusCode finalize () override
virtual void before (const std::string &event, const std::string &name, const EventContext &ctx) override
 Auditor hooks.
virtual void after (const std::string &event, const std::string &name, const EventContext &ctx, const StatusCode &sc) override
MsgStream & msg () const
bool msgLvl (const MSG::Level lvl) const

Private Types

enum  { FPEAUDITOR_OVERFLOW =0 , FPEAUDITOR_INVALID =1 , FPEAUDITOR_DIVBYZERO =2 , FPEAUDITOR_ARRAYSIZE =3 }
typedef std::pair< int, int > FpeNode_t
typedef std::list< FpeNode_tFpeStack_t

Private Member Functions

void report_fpe (const std::string &step, const std::string &caller, const EventContext &ctx)
 report fpes which happened during step 'step' on behalf of 'caller'
void add_fpe_node ()
 add an fpe node
void pop_fpe_node ()
 pop an fpe node
void InstallHandler ()
void UninstallHandler ()

Private Attributes

std::atomic< unsigned int > m_CountFPEs [FPEAUDITOR_ARRAYSIZE]
unsigned int m_NstacktracesOnFPE =0
unsigned int m_Nstacklines =100
fenv_t m_env
 The FP environment before we initialize.
std::atomic< int > m_nexceptions

Static Private Attributes

static thread_local FpeStack_t s_fpe_stack
 a stack of FPE exceptions which have been raised

Detailed Description

Definition at line 33 of file FPEAuditor.h.

Member Typedef Documentation

◆ FpeNode_t

typedef std::pair<int,int> FPEAuditor::FpeNode_t
private

Definition at line 75 of file FPEAuditor.h.

◆ FpeStack_t

typedef std::list<FpeNode_t> FPEAuditor::FpeStack_t
private

Definition at line 76 of file FPEAuditor.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
private
Enumerator
FPEAUDITOR_OVERFLOW 
FPEAUDITOR_INVALID 
FPEAUDITOR_DIVBYZERO 
FPEAUDITOR_ARRAYSIZE 

Definition at line 81 of file FPEAuditor.h.

Constructor & Destructor Documentation

◆ FPEAuditor()

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

Constructor.

Definition at line 62 of file FPEAuditor.cxx.

63 :
64 AthCommonMsg<Auditor> ( name, pSvcLocator ),
66 m_env(),
68{
69 declareProperty("NStacktracesOnFPE", m_NstacktracesOnFPE,
70 "Flag to configure, how many stack traces in case of FPE are printed. "
71 "Default: Zero, just report that FPE has happened. "
72 "After collecting the stacktrace, the code has to modify the mcontext_t "
73 "struct to ignore FPEs for the rest of the processing of the algorithm/service "
74 "This part is highly non-portable!" );
75
76 declareProperty("Nstacklines", m_Nstacklines,"Limit how deep we dive into the stack");
77}
std::atomic< int > m_nexceptions
Definition FPEAuditor.h:98
unsigned int m_NstacktracesOnFPE
Definition FPEAuditor.h:85
std::atomic< unsigned int > m_CountFPEs[FPEAUDITOR_ARRAYSIZE]
Definition FPEAuditor.h:83
fenv_t m_env
The FP environment before we initialize.
Definition FPEAuditor.h:96
unsigned int m_Nstacklines
Definition FPEAuditor.h:87

◆ ~FPEAuditor()

FPEAuditor::~FPEAuditor ( )
virtual

Destructor.

Definition at line 83 of file FPEAuditor.cxx.

84{
85 //m_msg << MSG::DEBUG << "Calling destructor" << endmsg;
86}

Member Function Documentation

◆ add_fpe_node()

void FPEAuditor::add_fpe_node ( )
private

add an fpe node

Definition at line 278 of file FPEAuditor.cxx.

279{
280 // get current list of FPE flags so far
281 int raised = fetestexcept(FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
282 s_fpe_stack.push_back(std::make_pair(raised, 0));
283
284 // clear FPE status word
285 feclearexcept(FE_ALL_EXCEPT);
286
288 // Make sure exceptions have been masked off if the handler has been
289 // disabled. Yes, this is already done in the signal handler.
290 // But when TBB starts a new task, it resets the FPU control words
291 // to values that were copied when the thread pool was initialized.
292 // FIXME: Do it properly with TBB? Not sure that the current
293 // interfaces allow it.
294 FPEAudit::mask_fpe();
295 }
296}
static thread_local FpeStack_t s_fpe_stack
a stack of FPE exceptions which have been raised
Definition FPEAuditor.h:79
std::atomic< bool > s_handlerDisabled

◆ after()

void FPEAuditor::after ( const std::string & event,
const std::string & name,
const EventContext & ctx,
const StatusCode & sc )
overridevirtual

Definition at line 178 of file FPEAuditor.cxx.

180{
181 report_fpe(event, name, ctx);
182 pop_fpe_node();
183
184 if ( event==IAuditor::Initialize ) {
186 // CoreDumpSvc can also install a FPE handler, grrr.
187 if (name == "CoreDumpSvc") FPEAudit::s_handlerInstalled = false;
191 }
192 }
193}
void InstallHandler()
void report_fpe(const std::string &step, const std::string &caller, const EventContext &ctx)
report fpes which happened during step 'step' on behalf of 'caller'
void pop_fpe_node()
pop an fpe node
std::lock_guard< std::mutex > lock_t
std::mutex s_mutex
std::atomic< bool > s_handlerInstalled

◆ before()

void FPEAuditor::before ( const std::string & event,
const std::string & name,
const EventContext & ctx )
overridevirtual

Auditor hooks.

Definition at line 162 of file FPEAuditor.cxx.

164{
165 add_fpe_node();
166
167 if ( event==IAuditor::Execute ) {
173 }
174 }
175 }
176}
void add_fpe_node()
add an fpe node

◆ finalize()

StatusCode FPEAuditor::finalize ( )
overridevirtual

Definition at line 100 of file FPEAuditor.cxx.

101{
102 ATH_MSG_INFO("FPE summary for this job");
103 ATH_MSG_INFO(" FPE OVERFLOWs : " << m_CountFPEs[FPEAUDITOR_OVERFLOW] );
104 ATH_MSG_INFO(" FPE INVALIDs : " << m_CountFPEs[FPEAUDITOR_INVALID]);
105 ATH_MSG_INFO(" FPE DIVBYZEROs : " << m_CountFPEs[FPEAUDITOR_DIVBYZERO]);
106
107 {
111 }
112
113 return StatusCode::SUCCESS;
114}
#define ATH_MSG_INFO(x)
void UninstallHandler()

◆ initialize()

StatusCode FPEAuditor::initialize ( )
overridevirtual

Gaudi hooks.

Definition at line 88 of file FPEAuditor.cxx.

89{
90 for ( unsigned int i(0); i<FPEAUDITOR_ARRAYSIZE; ++i )
91 m_CountFPEs[i]=0;
92 //ATH_MSG_INFO("==> initialize");
93 // add a fake node here because we may come alive while the AuditorSvc is
94 // still initializing (so one edge is left orphaned)
96
97 return StatusCode::SUCCESS;
98}

◆ InstallHandler()

void FPEAuditor::InstallHandler ( )
private

Definition at line 116 of file FPEAuditor.cxx.

117{
118 // Save the current FP environment.
119 fegetenv (&m_env);
120
121#ifdef __aarch64__
122 ATH_MSG_WARNING("Collecting stack traces for FPES is not supported on aarch64");
126#else
127 struct sigaction act;
128 memset(&act, 0, sizeof act);
129 act.sa_sigaction = FPEAudit::fpe_sig_action;
130 act.sa_flags = SA_SIGINFO;
131 if ( sigaction(SIGFPE, &act, &FPEAudit::s_oldactHandler) != 0 )
132 {
133 ATH_MSG_WARNING ("Printing stacktraces on FPE requested, but unable to install signal handler ! Switched off !");
135 }
137 {
138 ATH_MSG_INFO ("Installed Signalhandler !");
139 FPEAudit::unmask_fpe();
140 }
144
146#endif
147}
#define ATH_MSG_WARNING(x)
thread_local FPEAuditTLSData s_tlsdata
void * s_array_D[MAXARRAY]
void * s_array_O[MAXARRAY]
void * s_array_I[MAXARRAY]

◆ msg()

MsgStream & AthCommonMsg< Gaudi::Auditor >::msg ( ) const
inlineinherited

Definition at line 24 of file AthCommonMsg.h.

24 {
25 return this->msgStream();
26 }

◆ msgLvl()

bool AthCommonMsg< Gaudi::Auditor >::msgLvl ( const MSG::Level lvl) const
inlineinherited

Definition at line 30 of file AthCommonMsg.h.

30 {
31 return this->msgLevel(lvl);
32 }

◆ pop_fpe_node()

void FPEAuditor::pop_fpe_node ( )
private

pop an fpe node

Definition at line 299 of file FPEAuditor.cxx.

300{
301 if (s_fpe_stack.empty()) {
302 ATH_MSG_ERROR("inconsistent fpe-stack !");
303 throw std::runtime_error("inconsistent fpe-stack");
304 }
305
306 // restore fpe stack info
307 int raised = s_fpe_stack.back().first;
308 s_fpe_stack.pop_back();
309
310 // consolidate
311 if (!s_fpe_stack.empty()) {
312 s_fpe_stack.back().second |= raised;
313 }
315 FPEAudit::unmask_fpe();
316 }
317}
#define ATH_MSG_ERROR(x)

◆ report_fpe()

void FPEAuditor::report_fpe ( const std::string & step,
const std::string & caller,
const EventContext & ctx )
private

report fpes which happened during step 'step' on behalf of 'caller'

Definition at line 198 of file FPEAuditor.cxx.

201{
202 // store current list of FPE flags which were raised before
203 int raised = fetestexcept(FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
204 if (raised) {
205 std::stringstream evStr;
206 if (ctx.valid()) {
207 evStr << " on event " << ctx.eventID().event_number();
208 }
209
210 if (raised & FE_OVERFLOW) {
211 ATH_MSG_WARNING("FPE OVERFLOW in [" << step << "] of [" << caller << "]" << evStr.str() <<
213 );
215 if ( m_NstacktracesOnFPE && FPEAudit::s_tlsdata.s_array_O[0] != NULL )
216 {
217 for (unsigned int j = 0; j < m_Nstacklines; j++)
218 {
220 if (FPEAudit::s_tlsdata.s_array_O[j]==NULL) break;
221 this->msg(MSG::INFO) << "FPE stacktrace " << j << " :\n";
222 FPEAudit::resolve(FPEAudit::s_tlsdata.s_array_O[j],this->msg());
224 this->msg(MSG::INFO) << endmsg;
225 }
226 }
227 }
228 if (raised & FE_INVALID) {
229 ATH_MSG_WARNING("FPE INVALID in [" << step << "] of [" << caller << "]" << evStr.str()
231 );
233 }
234 if ( m_NstacktracesOnFPE && FPEAudit::s_tlsdata.s_array_I[0] != NULL )
235 {
236 for (unsigned int j = 0; j < m_Nstacklines; j++)
237 {
239 if (FPEAudit::s_tlsdata.s_array_I[j]==NULL) break;
240 this->msg(MSG::INFO) << "FPE stacktrace " << j << " :\n";
241 FPEAudit::resolve(FPEAudit::s_tlsdata.s_array_I[j],this->msg());
243 this->msg(MSG::INFO) << endmsg;
244 }
245 }
246 if (raised & FE_DIVBYZERO) {
247 ATH_MSG_WARNING("FPE DIVBYZERO in [" << step << "] of [" << caller << "]" << evStr.str()
249 );
251 if ( m_NstacktracesOnFPE && FPEAudit::s_tlsdata.s_array_D[0] != NULL )
252 {
254 for (unsigned int j = 0; j < m_Nstacklines; j++)
255 {
256 if (FPEAudit::s_tlsdata.s_array_D[j]==NULL) break;
257 this->msg(MSG::INFO) << "FPE stacktrace " << j << " :\n";
258 FPEAudit::resolve(FPEAudit::s_tlsdata.s_array_D[j],this->msg());
260 this->msg(MSG::INFO) << endmsg;
261 }
262 }
263 }
264
265
267 if ( --m_nexceptions == 0
270 {
271 fprintf(stderr, "too many SIGFPE detected, will be uninstalling signal handler\n");
273 }
274 }
275}
#define endmsg

◆ UninstallHandler()

void FPEAuditor::UninstallHandler ( )
private

Definition at line 149 of file FPEAuditor.cxx.

150{
151 ATH_MSG_INFO("uninstalling SignalHandler");
153
154 feclearexcept(FE_ALL_EXCEPT);
155 fesetenv (&m_env);
156 FPEAudit::mask_fpe();
157
158 // feenableexcept (0);
159 // fedisableexcept (FE_ALL_EXCEPT);
160}

Member Data Documentation

◆ m_CountFPEs

std::atomic<unsigned int> FPEAuditor::m_CountFPEs[FPEAUDITOR_ARRAYSIZE]
private

Definition at line 83 of file FPEAuditor.h.

◆ m_env

fenv_t FPEAuditor::m_env
private

The FP environment before we initialize.

Definition at line 96 of file FPEAuditor.h.

◆ m_nexceptions

std::atomic<int> FPEAuditor::m_nexceptions
private

Definition at line 98 of file FPEAuditor.h.

◆ m_Nstacklines

unsigned int FPEAuditor::m_Nstacklines =100
private

Definition at line 87 of file FPEAuditor.h.

◆ m_NstacktracesOnFPE

unsigned int FPEAuditor::m_NstacktracesOnFPE =0
private

Definition at line 85 of file FPEAuditor.h.

◆ s_fpe_stack

thread_local FPEAuditor::FpeStack_t FPEAuditor::s_fpe_stack
staticprivate

a stack of FPE exceptions which have been raised

Definition at line 79 of file FPEAuditor.h.


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