ATLAS Offline Software
Loading...
Searching...
No Matches
RootUtils::WithRootErrorHandler Class Reference

Run a MT piece of code with an alternate root error handler. More...

#include <WithRootErrorHandler.h>

Collaboration diagram for RootUtils::WithRootErrorHandler:

Public Types

using Handler_t = std::function<bool (int, Bool_t, const char*, const char*)>
 Type of handler to register.

Public Member Functions

 WithRootErrorHandler (Handler_t errhand)
 Temporarily install a thread-local root error handler.
 ~WithRootErrorHandler ()
 Destructor.
 WithRootErrorHandler (const WithRootErrorHandler &)=delete
 WithRootErrorHandler (WithRootErrorHandler &&)=delete
WithRootErrorHandleroperator= (const WithRootErrorHandler &)=delete
WithRootErrorHandleroperator= (WithRootErrorHandler &&)=delete

Static Public Member Functions

static void * operator new (size_t)=delete
static void * operator new[] (size_t)=delete
static void operator delete (void *)=delete
static void operator delete[] (void *)=delete

Private Attributes

size_t m_size
 For error checking.

Detailed Description

Run a MT piece of code with an alternate root error handler.

Sometimes we want to run a piece of code with an alternate root error handler. This is however problematic in MT jobs since the root error handler pointer is just a global variable visible in all threads. We also frequently need to introduce additional globals if we need to communicate with the handler.

This piece of code tries to get around these limitations. It installs a single root error handler during initialization. This handler will then dispatch to other handlers stored in thread-local storage. This effectively makes changing the root error handler thread-local. We also manage the handler as a std::function, allowing it to have associated state, and clean up the change using RAII.

To change the root error handler, create an instance of this class, passing it a function object, which should have signature:

bool hand (int level, bool abort, const char* location, const char* msg)
MsgStream & msg
Definition testRead.cxx:32

The arguments are the same as for standard root error handlers. The handler should return true if previous handlers should also be called. If a handler returns false, no further handlers will be called.

The change in the error handler is visible only in the current thread, and the revious handler will be restored when the object is deleted.

Definition at line 55 of file WithRootErrorHandler.h.

Member Typedef Documentation

◆ Handler_t

using RootUtils::WithRootErrorHandler::Handler_t = std::function<bool (int, Bool_t, const char*, const char*)>

Type of handler to register.

Like a ROOT error handler, except that it returns a bool.

Definition at line 63 of file WithRootErrorHandler.h.

Constructor & Destructor Documentation

◆ WithRootErrorHandler() [1/3]

RootUtils::WithRootErrorHandler::WithRootErrorHandler ( Handler_t errhand)

Temporarily install a thread-local root error handler.

Parameters
errhandThe handler to be installed.

The installed handler will only run in the current thread, and it will be removed when this object is deleted. In addition to the usual arguments for a root error handler, it returns a bool. If the returned value is true, previous handlers will also be executed; otherwise, no further handlers will be executed.

Definition at line 65 of file WithRootErrorHandler.cxx.

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}
static void errorHandler()
bool flag
Definition master.py:29

◆ ~WithRootErrorHandler()

RootUtils::WithRootErrorHandler::~WithRootErrorHandler ( )

Destructor.

Remove the error handler.

Definition at line 98 of file WithRootErrorHandler.cxx.

99{
100 if (m_size != rootErrorHandlers.size()) std::abort();
101 rootErrorHandlers.pop_back();
102}

◆ WithRootErrorHandler() [2/3]

RootUtils::WithRootErrorHandler::WithRootErrorHandler ( const WithRootErrorHandler & )
delete

◆ WithRootErrorHandler() [3/3]

RootUtils::WithRootErrorHandler::WithRootErrorHandler ( WithRootErrorHandler && )
delete

Member Function Documentation

◆ operator delete()

void RootUtils::WithRootErrorHandler::operator delete ( void * )
staticdelete

◆ operator delete[]()

void RootUtils::WithRootErrorHandler::operator delete[] ( void * )
staticdelete

◆ operator new()

void * RootUtils::WithRootErrorHandler::operator new ( size_t )
staticdelete

◆ operator new[]()

void * RootUtils::WithRootErrorHandler::operator new[] ( size_t )
staticdelete

◆ operator=() [1/2]

WithRootErrorHandler & RootUtils::WithRootErrorHandler::operator= ( const WithRootErrorHandler & )
delete

◆ operator=() [2/2]

WithRootErrorHandler & RootUtils::WithRootErrorHandler::operator= ( WithRootErrorHandler && )
delete

Member Data Documentation

◆ m_size

size_t RootUtils::WithRootErrorHandler::m_size
private

For error checking.

Definition at line 101 of file WithRootErrorHandler.h.


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