From df1a970b45c61f809356cb316ef18120f3120346 Mon Sep 17 00:00:00 2001 From: Marco Clemencic <marco.clemencic@cern.ch> Date: Fri, 20 Jan 2023 17:47:13 +0100 Subject: [PATCH] Use MessageSvc to handle ROOT messages --- .../src/ApplicationMgr/ApplicationMgr.cpp | 72 ++++++++++++------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/GaudiCoreSvc/src/ApplicationMgr/ApplicationMgr.cpp b/GaudiCoreSvc/src/ApplicationMgr/ApplicationMgr.cpp index adec52296e..75f11b2133 100644 --- a/GaudiCoreSvc/src/ApplicationMgr/ApplicationMgr.cpp +++ b/GaudiCoreSvc/src/ApplicationMgr/ApplicationMgr.cpp @@ -1,5 +1,5 @@ /***********************************************************************************\ -* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations * +* (c) Copyright 1998-2023 CERN for the benefit of the LHCb and ATLAS collaborations * * * * This software is distributed under the terms of the Apache version 2 licence, * * copied verbatim in the file "LICENSE". * @@ -9,44 +9,61 @@ * or submit itself to any jurisdiction. * \***********************************************************************************/ -// Include files #include "ApplicationMgr.h" - #include "AlgorithmManager.h" #include "DLLClassManager.h" #include "ServiceManager.h" - -#include "GaudiKernel/IMessageSvc.h" -#include "GaudiKernel/IRunable.h" -#include "GaudiKernel/IService.h" -#include "GaudiKernel/TypeNameString.h" - -#include "GaudiKernel/MsgStream.h" -#include "GaudiKernel/ObjectFactory.h" -#include "GaudiKernel/SmartIF.h" - -#include "GaudiKernel/GaudiException.h" - -#include "GaudiKernel/StatusCode.h" -#include "GaudiKernel/System.h" -#include "GaudiKernel/Time.h" - -#include "GAUDI_VERSION.h" - -using System::getEnv; -using System::isEnvSet; - +#include <GAUDI_VERSION.h> +#include <GaudiKernel/GaudiException.h> +#include <GaudiKernel/IMessageSvc.h> +#include <GaudiKernel/IRunable.h> +#include <GaudiKernel/IService.h> +#include <GaudiKernel/Message.h> +#include <GaudiKernel/MsgStream.h> +#include <GaudiKernel/ObjectFactory.h> +#include <GaudiKernel/SmartIF.h> +#include <GaudiKernel/StatusCode.h> +#include <GaudiKernel/System.h> +#include <GaudiKernel/Time.h> +#include <GaudiKernel/TypeNameString.h> +#include <TError.h> +#include <TROOT.h> #include <algorithm> #include <cassert> #include <ctime> #include <limits> #include <sstream> +using System::getEnv; +using System::isEnvSet; + #define ON_DEBUG if ( m_outputLevel <= MSG::DEBUG ) #define ON_VERBOSE if ( m_outputLevel <= MSG::VERBOSE ) DECLARE_OBJECT_FACTORY( ApplicationMgr ) +namespace { + /// Pointer to the IMessageSvc instance used by ROOTErrorHandlerAdapter. + static IMessageSvc* s_messageSvcInstance{ nullptr }; + + /// @brief Adapter to forward ROOT messages to a MessageSvc. + void ROOTErrorHandlerAdapter( int level, Bool_t abort, const char* location, const char* msg ) { + if ( s_messageSvcInstance ) { + // # Map ROOT level to Gaudi level: + // ROOT levels go from 0 to 6000 in step of 1000, + // kInfo is 1000 while MSG::INFO is 3, so we aim for `level / 1000 + 2`, + // but we have to put a cap at MSG::FATAL. + int msgLevel = std::min<int>( level / 1000 + 2, MSG::FATAL ); + if ( msgLevel >= s_messageSvcInstance->outputLevel( location ) ) + s_messageSvcInstance->reportMessage( Message{ location, msgLevel, msg }, msgLevel ); + } else { + // If a message is sent when we do not have an IMessageSvc, let's use a basic implementation from ROOT + ROOT::Internal::MinimalErrorHandler( level, abort, location, msg ); + } + } + +} // namespace + // Implementation class for the Application Manager. In this way the // ApplicationMgr class is a fully insulated concrete class. Clients // (main programs) will not need to re-compile if there are changes @@ -145,6 +162,11 @@ StatusCode ApplicationMgr::i_startup() { log << MSG::FATAL << "Error setting OutputLevel option of MessageSvc" << endmsg; return sc; } + if ( gROOT ) { + // if ROOT is already initialized (usually it is the case) we redirect messages to MessageSvc. + s_messageSvcInstance = m_messageSvc.get(); + SetErrorHandler( ROOTErrorHandlerAdapter ); + } auto jobsvc = svcManager()->createService( Gaudi::Utils::TypeNameString( "JobOptionsSvc", m_jobOptionsSvcType ) ); // Create the Job Options service @@ -620,6 +642,8 @@ StatusCode ApplicationMgr::terminate() { opts.set( "JobOptionsSvc.AuditFinalize", "false" ); } + // make sure ROOTErrorHandlerAdapter (if in use) does not try to use the MessageSvc we are about to delete + s_messageSvcInstance = nullptr; // finalize MessageSvc auto svc = m_messageSvc.as<IService>(); if ( !svc ) { -- GitLab