ATLAS Offline Software
Public Types | Public Member Functions | Static Public Member Functions | Private Attributes | List of all members
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. More...
 

Public Member Functions

 WithRootErrorHandler (Handler_t errhand)
 Temporarily install a thread-local root error handler. More...
 
 ~WithRootErrorHandler ()
 Destructor. More...
 
 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. More...
 

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)

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 }

◆ ~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()

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

◆ operator delete[]()

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

◆ operator new()

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

◆ operator new[]()

static 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:
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
master.flag
bool flag
Definition: master.py:29
RootUtils::WithRootErrorHandler::m_size
size_t m_size
For error checking.
Definition: WithRootErrorHandler.h:101
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7