ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Control
AthenaAuditors
src
FPEAuditor.cxx
Go to the documentation of this file.
1
2
3
/*
4
Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5
*/
6
7
// FPEAuditor.cxx
8
// Implementation file for class FPEAuditor
9
// Author: S.Binet<binet@cern.ch>
11
12
#include <stdexcept>
13
#include <mutex>
14
#include <atomic>
15
16
// FrameWork includes
17
#include "GaudiKernel/INamedInterface.h"
18
#include "GaudiKernel/EventContext.h"
19
20
#include "
FPEAuditor.h
"
21
22
#include "
CxxUtils/checker_macros.h
"
23
24
// C includes
25
#include <fenv.h>
26
27
28
namespace
FPEAudit
{
29
const
int
MAXARRAY
=100;
30
struct
FPEAuditTLSData
{
31
void
*
s_array_O
[
MAXARRAY
];
32
void
*
s_array_I
[
MAXARRAY
];
33
void
*
s_array_D
[
MAXARRAY
];
34
};
35
36
thread_local
FPEAuditTLSData
s_tlsdata
;
37
38
std::atomic<bool>
s_handlerInstalled
=
false
;
39
std::atomic<bool>
s_handlerDisabled
=
false
;
40
struct
sigaction s_oldactHandler
ATLAS_THREAD_SAFE
;
41
42
std::mutex
s_mutex
;
43
typedef
std::lock_guard<std::mutex>
lock_t
;
44
}
45
46
47
#if defined(__linux__) && ( defined(__i386__) || defined(__x86_64__) )
48
# include "
FPEAudit_linux.icc
"
49
#else
50
# include "
FPEAudit_dummy.icc
"
51
#endif
52
53
55
// Public methods:
57
58
// Constructors
60
FPEAuditor::FPEAuditor
(
const
std::string& name,
61
ISvcLocator* pSvcLocator ) :
62
AthCommonMsg
<Auditor> ( name, pSvcLocator ),
63
m_CountFPEs
(),
64
m_env
(),
65
m_nexceptions
(0)
66
{
67
declareProperty(
"NStacktracesOnFPE"
,
m_NstacktracesOnFPE
,
68
"Flag to configure, how many stack traces in case of FPE are printed. "
69
"Default: Zero, just report that FPE has happened. "
70
"After collecting the stacktrace, the code has to modify the mcontext_t "
71
"struct to ignore FPEs for the rest of the processing of the algorithm/service "
72
"This part is highly non-portable!"
);
73
74
declareProperty(
"Nstacklines"
,
m_Nstacklines
,
"Limit how deep we dive into the stack"
);
75
}
76
77
// Destructor
79
#include <fstream>
80
#include <iomanip>
81
FPEAuditor::~FPEAuditor
()
82
{
83
//m_msg << MSG::DEBUG << "Calling destructor" << endmsg;
84
}
85
86
StatusCode
FPEAuditor::initialize
()
87
{
88
for
(
unsigned
int
i(0); i<
FPEAUDITOR_ARRAYSIZE
; ++i )
89
m_CountFPEs
[i]=0;
90
//ATH_MSG_INFO("==> initialize");
91
// add a fake node here because we may come alive while the AuditorSvc is
92
// still initializing (so one edge is left orphaned)
93
add_fpe_node
();
94
95
return
StatusCode::SUCCESS;
96
}
97
98
StatusCode
FPEAuditor::finalize
()
99
{
100
ATH_MSG_INFO
(
"FPE summary for this job"
);
101
ATH_MSG_INFO
(
" FPE OVERFLOWs : "
<<
m_CountFPEs
[
FPEAUDITOR_OVERFLOW
] );
102
ATH_MSG_INFO
(
" FPE INVALIDs : "
<<
m_CountFPEs
[
FPEAUDITOR_INVALID
]);
103
ATH_MSG_INFO
(
" FPE DIVBYZEROs : "
<<
m_CountFPEs
[
FPEAUDITOR_DIVBYZERO
]);
104
105
{
106
FPEAudit::lock_t
lock
(
FPEAudit::s_mutex
);
107
if
(
FPEAudit::s_handlerInstalled
&& !
FPEAudit::s_handlerDisabled
)
108
UninstallHandler
();
109
}
110
111
return
StatusCode::SUCCESS;
112
}
113
114
void
FPEAuditor::InstallHandler
()
115
{
116
// Save the current FP environment.
117
fegetenv (&
m_env
);
118
119
#ifdef __aarch64__
120
ATH_MSG_WARNING
(
"Collecting stack traces for FPES is not supported on aarch64"
);
121
m_NstacktracesOnFPE
= 0;
122
FPEAudit::s_handlerDisabled
=
true
;
123
FPEAudit::s_handlerInstalled
=
true
;
124
#else
125
struct
sigaction act;
126
memset(&act, 0,
sizeof
act);
127
act.sa_sigaction = FPEAudit::fpe_sig_action;
128
act.sa_flags = SA_SIGINFO;
129
if
( sigaction(SIGFPE, &act, &FPEAudit::s_oldactHandler) != 0 )
130
{
131
ATH_MSG_WARNING
(
"Printing stacktraces on FPE requested, but unable to install signal handler ! Switched off !"
);
132
m_NstacktracesOnFPE
=0;
133
}
134
if
(
m_NstacktracesOnFPE
)
135
{
136
ATH_MSG_INFO
(
"Installed Signalhandler !"
);
137
FPEAudit::unmask_fpe();
138
}
139
FPEAudit::s_tlsdata
.s_array_O[0]=NULL;
140
FPEAudit::s_tlsdata
.s_array_I[0]=NULL;
141
FPEAudit::s_tlsdata
.s_array_D[0]=NULL;
142
143
FPEAudit::s_handlerInstalled
=
true
;
144
#endif
145
}
146
147
void
FPEAuditor::UninstallHandler
()
148
{
149
ATH_MSG_INFO
(
"uninstalling SignalHandler"
);
150
FPEAudit::s_handlerDisabled
=
true
;
151
152
feclearexcept(FE_ALL_EXCEPT);
153
fesetenv (&
m_env
);
154
FPEAudit::mask_fpe();
155
156
// feenableexcept (0);
157
// fedisableexcept (FE_ALL_EXCEPT);
158
}
159
160
void
FPEAuditor::before
(
const
std::string& event,
const
std::string&
/*name*/
,
161
const
EventContext&)
162
{
163
add_fpe_node
();
164
165
if
( event==IAuditor::Execute ) {
166
if
(
m_NstacktracesOnFPE
&& !
FPEAudit::s_handlerInstalled
) {
167
FPEAudit::lock_t
lock
(
FPEAudit::s_mutex
);
168
if
(
m_NstacktracesOnFPE
&& !
FPEAudit::s_handlerInstalled
) {
169
InstallHandler
();
170
m_nexceptions
=
m_NstacktracesOnFPE
;
171
}
172
}
173
}
174
}
175
176
void
FPEAuditor::after
(
const
std::string& event,
const
std::string& name,
177
const
EventContext& ctx,
const
StatusCode&)
178
{
179
report_fpe
(event, name, ctx);
180
pop_fpe_node
();
181
182
if
( event==IAuditor::Initialize ) {
183
FPEAudit::lock_t
lock
(
FPEAudit::s_mutex
);
184
// CoreDumpSvc can also install a FPE handler, grrr.
185
if
(name ==
"CoreDumpSvc"
)
FPEAudit::s_handlerInstalled
=
false
;
186
if
(
m_NstacktracesOnFPE
&& !
FPEAudit::s_handlerInstalled
) {
187
InstallHandler
();
188
m_nexceptions
=
m_NstacktracesOnFPE
;
189
}
190
}
191
}
192
195
void
196
FPEAuditor::report_fpe
(
const
std::string& step,
197
const
std::string& caller,
198
const
EventContext& ctx)
199
{
200
// store current list of FPE flags which were raised before
201
int
raised = fetestexcept(FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO);
202
if
(raised) {
203
std::stringstream evStr;
204
if
(ctx.valid()) {
205
evStr <<
" on event "
<< ctx.eventID().event_number();
206
}
207
208
if
(raised & FE_OVERFLOW) {
209
ATH_MSG_WARNING
(
"FPE OVERFLOW in ["
<< step <<
"] of ["
<< caller <<
"]"
<< evStr.str() <<
210
" "
<<
m_NstacktracesOnFPE
<<
" "
<<
FPEAudit::s_tlsdata
.s_array_O[0]
211
);
212
++
m_CountFPEs
[
FPEAUDITOR_OVERFLOW
];
213
if
(
m_NstacktracesOnFPE
&&
FPEAudit::s_tlsdata
.s_array_O[0] != NULL )
214
{
215
for
(
unsigned
int
j = 0; j <
m_Nstacklines
; j++)
216
{
217
FPEAudit::lock_t
lock
(
FPEAudit::s_mutex
);
218
if
(
FPEAudit::s_tlsdata
.s_array_O[j]==NULL)
break
;
219
this->
msg
(MSG::INFO) <<
"FPE stacktrace "
<< j <<
" :\n"
;
220
FPEAudit::resolve(
FPEAudit::s_tlsdata
.s_array_O[j],this->
msg
());
221
FPEAudit::s_tlsdata
.s_array_O[j]=NULL;
222
this->
msg
(MSG::INFO) <<
endmsg
;
223
}
224
}
225
}
226
if
(raised & FE_INVALID) {
227
ATH_MSG_WARNING
(
"FPE INVALID in ["
<< step <<
"] of ["
<< caller <<
"]"
<< evStr.str()
228
<<
" "
<<
m_NstacktracesOnFPE
<<
" "
<<
FPEAudit::s_tlsdata
.s_array_I[0]
229
);
230
++
m_CountFPEs
[
FPEAUDITOR_INVALID
];
231
}
232
if
(
m_NstacktracesOnFPE
&&
FPEAudit::s_tlsdata
.s_array_I[0] != NULL )
233
{
234
for
(
unsigned
int
j = 0; j <
m_Nstacklines
; j++)
235
{
236
FPEAudit::lock_t
lock
(
FPEAudit::s_mutex
);
237
if
(
FPEAudit::s_tlsdata
.s_array_I[j]==NULL)
break
;
238
this->
msg
(MSG::INFO) <<
"FPE stacktrace "
<< j <<
" :\n"
;
239
FPEAudit::resolve(
FPEAudit::s_tlsdata
.s_array_I[j],this->
msg
());
240
FPEAudit::s_tlsdata
.s_array_I[j]=NULL;
241
this->
msg
(MSG::INFO) <<
endmsg
;
242
}
243
}
244
if
(raised & FE_DIVBYZERO) {
245
ATH_MSG_WARNING
(
"FPE DIVBYZERO in ["
<< step <<
"] of ["
<< caller <<
"]"
<< evStr.str()
246
<<
" "
<<
m_NstacktracesOnFPE
<<
" "
<<
FPEAudit::s_tlsdata
.s_array_D[0]
247
);
248
++
m_CountFPEs
[
FPEAUDITOR_DIVBYZERO
];
249
if
(
m_NstacktracesOnFPE
&&
FPEAudit::s_tlsdata
.s_array_D[0] != NULL )
250
{
251
FPEAudit::lock_t
lock
(
FPEAudit::s_mutex
);
252
for
(
unsigned
int
j = 0; j <
m_Nstacklines
; j++)
253
{
254
if
(
FPEAudit::s_tlsdata
.s_array_D[j]==NULL)
break
;
255
this->
msg
(MSG::INFO) <<
"FPE stacktrace "
<< j <<
" :\n"
;
256
FPEAudit::resolve(
FPEAudit::s_tlsdata
.s_array_D[j],this->
msg
());
257
FPEAudit::s_tlsdata
.s_array_D[j]=NULL;
258
this->
msg
(MSG::INFO) <<
endmsg
;
259
}
260
}
261
}
262
263
264
FPEAudit::lock_t
lock
(
FPEAudit::s_mutex
);
265
if
( --
m_nexceptions
== 0
266
&&
FPEAudit::s_handlerInstalled
&&
267
!
FPEAudit::s_handlerDisabled
)
268
{
269
fprintf(stderr,
"too many SIGFPE detected, will be uninstalling signal handler\n"
);
270
UninstallHandler
();
271
}
272
}
273
}
274
275
void
276
FPEAuditor::add_fpe_node
()
277
{
278
// clear FPE status word
279
feclearexcept(FE_ALL_EXCEPT);
280
281
if
(
FPEAudit::s_handlerDisabled
) {
282
// Make sure exceptions have been masked off if the handler has been
283
// disabled. Yes, this is already done in the signal handler.
284
// But when TBB starts a new task, it resets the FPU control words
285
// to values that were copied when the thread pool was initialized.
286
// FIXME: Do it properly with TBB? Not sure that the current
287
// interfaces allow it.
288
FPEAudit::mask_fpe();
289
}
290
}
291
292
void
293
FPEAuditor::pop_fpe_node
()
294
{
295
if
(
FPEAudit::s_handlerInstalled
&& !
FPEAudit::s_handlerDisabled
) {
296
FPEAudit::unmask_fpe();
297
}
298
}
endmsg
#define endmsg
Definition
AnalysisConfig_Ntuple.cxx:54
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition
AthMsgStreamMacros.h:31
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition
AthMsgStreamMacros.h:32
FPEAudit_dummy.icc
FPEAudit_linux.icc
FPEAuditor.h
lock
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
checker_macros.h
Define macros for attributes used to control the static checker.
AthCommonMsg
Definition
AthCommonMsg.h:19
AthCommonMsg< Gaudi::Auditor >::msg
MsgStream & msg() const
Definition
AthCommonMsg.h:24
FPEAuditor::m_nexceptions
std::atomic< int > m_nexceptions
Definition
FPEAuditor.h:92
FPEAuditor::m_NstacktracesOnFPE
unsigned int m_NstacktracesOnFPE
Definition
FPEAuditor.h:79
FPEAuditor::FPEAUDITOR_INVALID
@ FPEAUDITOR_INVALID
Definition
FPEAuditor.h:75
FPEAuditor::FPEAUDITOR_ARRAYSIZE
@ FPEAUDITOR_ARRAYSIZE
Definition
FPEAuditor.h:75
FPEAuditor::FPEAUDITOR_DIVBYZERO
@ FPEAUDITOR_DIVBYZERO
Definition
FPEAuditor.h:75
FPEAuditor::FPEAUDITOR_OVERFLOW
@ FPEAUDITOR_OVERFLOW
Definition
FPEAuditor.h:75
FPEAuditor::m_CountFPEs
std::atomic< unsigned int > m_CountFPEs[FPEAUDITOR_ARRAYSIZE]
Definition
FPEAuditor.h:77
FPEAuditor::finalize
virtual StatusCode finalize() override
Definition
FPEAuditor.cxx:98
FPEAuditor::after
virtual void after(const std::string &event, const std::string &name, const EventContext &ctx, const StatusCode &sc) override
Definition
FPEAuditor.cxx:176
FPEAuditor::InstallHandler
void InstallHandler()
Definition
FPEAuditor.cxx:114
FPEAuditor::FPEAuditor
FPEAuditor(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
Definition
FPEAuditor.cxx:60
FPEAuditor::before
virtual void before(const std::string &event, const std::string &name, const EventContext &ctx) override
Auditor hooks.
Definition
FPEAuditor.cxx:160
FPEAuditor::~FPEAuditor
virtual ~FPEAuditor()
Destructor.
Definition
FPEAuditor.cxx:81
FPEAuditor::add_fpe_node
void add_fpe_node()
add an fpe node
Definition
FPEAuditor.cxx:276
FPEAuditor::m_env
fenv_t m_env
The FP environment before we initialize.
Definition
FPEAuditor.h:90
FPEAuditor::initialize
virtual StatusCode initialize() override
Gaudi hooks.
Definition
FPEAuditor.cxx:86
FPEAuditor::report_fpe
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'
Definition
FPEAuditor.cxx:196
FPEAuditor::UninstallHandler
void UninstallHandler()
Definition
FPEAuditor.cxx:147
FPEAuditor::m_Nstacklines
unsigned int m_Nstacklines
Definition
FPEAuditor.h:81
FPEAuditor::pop_fpe_node
void pop_fpe_node()
pop an fpe node
Definition
FPEAuditor.cxx:293
FPEAudit
Definition
FPEAuditor.cxx:28
FPEAudit::lock_t
std::lock_guard< std::mutex > lock_t
Definition
FPEAuditor.cxx:43
FPEAudit::s_mutex
std::mutex s_mutex
Definition
FPEAuditor.cxx:42
FPEAudit::ATLAS_THREAD_SAFE
struct sigaction s_oldactHandler ATLAS_THREAD_SAFE
Definition
FPEAuditor.cxx:40
FPEAudit::s_tlsdata
FPEAuditTLSData s_tlsdata
Definition
FPEAuditor.cxx:36
FPEAudit::s_handlerDisabled
std::atomic< bool > s_handlerDisabled
Definition
FPEAuditor.cxx:39
FPEAudit::s_handlerInstalled
std::atomic< bool > s_handlerInstalled
Definition
FPEAuditor.cxx:38
FPEAudit::MAXARRAY
const int MAXARRAY
Definition
FPEAuditor.cxx:29
FPEAudit::FPEAuditTLSData
Definition
FPEAuditor.cxx:30
FPEAudit::FPEAuditTLSData::s_array_D
void * s_array_D[MAXARRAY]
Definition
FPEAuditor.cxx:33
FPEAudit::FPEAuditTLSData::s_array_O
void * s_array_O[MAXARRAY]
Definition
FPEAuditor.cxx:31
FPEAudit::FPEAuditTLSData::s_array_I
void * s_array_I[MAXARRAY]
Definition
FPEAuditor.cxx:32
Generated on
for ATLAS Offline Software by
1.17.0