ATLAS Offline Software
Loading...
Searching...
No Matches
WithRootErrorHandler.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
3 */
10
11
13#include <vector>
14#include <cstdlib>
15#include <mutex>
16#include <atomic>
17
18
19namespace {
20
21
24thread_local std::vector<Handler_t> rootErrorHandlers;
25
26
28std::atomic<ErrorHandlerFunc_t> origHandler;
29
30
34void errorHandler (int level,
35 Bool_t abort,
36 const char* location,
37 const char* msg)
38{
39 // Execute all the handlers in our thread-local list from newest to oldest.
40 // Stop if one returns false.
41 for (int i = rootErrorHandlers.size()-1; i >= 0; --i) {
42 if (!rootErrorHandlers[i] (level, abort, location, msg)) return;
43 }
44 // They all returned true. Call the previous handler.
45 origHandler.load() (level, abort, location, msg);
46}
47
48
49} // anonymous namespace
50
51
52namespace RootUtils {
53
54
66 : m_size (rootErrorHandlers.size()+1)
67{
68 // Install our handler the first time we're called.
69 // We used to do that when the library was loaded, via a global static,
70 // but then we ran to issues where the behavior could depend on library
71 // loading order, since other libraries (such as Gaudi) also try to install
72 // their own handler.
73 //
74 // By the time we're called, there may be multiple threads running,
75 // so it is in principle not safe to call SetErrorHandler.
76 // However, there shouldn't be anything else in Athena calling it,
77 // so in practice it should be ok. As an extra check, we abort if the
78 // handler we get back isn't what we set, indicating a potential race.
79 //
80 // See ATLASRECTS-7967.
81 static std::once_flag flag;
82 std::call_once (flag, []() {
83 origHandler = ::SetErrorHandler (errorHandler);
84 if (::GetErrorHandler() != errorHandler) {
85 std::abort();
86 }
87 });
88
89 rootErrorHandlers.push_back (errhand);
90}
91
92
99{
100 if (m_size != rootErrorHandlers.size()) std::abort();
101 rootErrorHandlers.pop_back();
102}
103
104
105} // namespace RootUtils
static void errorHandler()
Run a MT piece of code with an alternate root error handler.
std::function< bool(int, Bool_t, const char *, const char *)> Handler_t
Type of handler to register.
WithRootErrorHandler(Handler_t errhand)
Temporarily install a thread-local root error handler.
MsgStream & msg
Definition testRead.cxx:32