CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/FWCore/Services/src/InitRootHandlers.cc

Go to the documentation of this file.
00001 #include "FWCore/Services/src/InitRootHandlers.h"
00002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00003 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00004 #include "FWCore/MessageLogger/interface/ELseverityLevel.h"
00005 #include "FWCore/Utilities/interface/EDMException.h"
00006 #include "FWCore/PluginManager/interface/PluginCapabilities.h"
00007 #include "FWCore/RootAutoLibraryLoader/interface/RootAutoLibraryLoader.h"
00008 #include "DataFormats/Provenance/interface/TransientStreamer.h"
00009 #include "DataFormats/Common/interface/CacheStreamers.h"
00010 #include "DataFormats/Common/interface/RefCoreStreamer.h"
00011 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
00012 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
00013 
00014 #include <string.h>
00015 #include <sstream>
00016 
00017 #include "TSystem.h"
00018 #include "TError.h"
00019 #include "TFile.h"
00020 #include "TTree.h"
00021 #include "TROOT.h"
00022 #include "Cintex/Cintex.h"
00023 #include "TH1.h"
00024 #include "G__ci.h"
00025 #include "Reflex/Type.h"
00026 
00027 namespace {
00028 
00029   void RootErrorHandler(int level, bool die, char const* location, char const* message) {
00030 
00031   // Translate ROOT severity level to MessageLogger severity level
00032 
00033     edm::ELseverityLevel el_severity = edm::ELseverityLevel::ELsev_info;
00034 
00035     if (level >= kFatal) {
00036       el_severity = edm::ELseverityLevel::ELsev_fatal;
00037     } else if (level >= kSysError) {
00038       el_severity = edm::ELseverityLevel::ELsev_severe;
00039     } else if (level >= kError) {
00040       el_severity = edm::ELseverityLevel::ELsev_error;
00041     } else if (level >= kWarning) {
00042       el_severity = edm::ELseverityLevel::ELsev_warning;
00043     }
00044 
00045   // Adapt C-strings to std::strings
00046   // Arrange to report the error location as furnished by Root
00047 
00048     std::string el_location = "@SUB=?";
00049     if (location != 0) el_location = std::string("@SUB=")+std::string(location);
00050 
00051     std::string el_message  = "?";
00052     if (message != 0) el_message  = message;
00053 
00054   // Try to create a meaningful id string using knowledge of ROOT error messages
00055   //
00056   // id ==     "ROOT-ClassName" where ClassName is the affected class
00057   //      else "ROOT/ClassName" where ClassName is the error-declaring class
00058   //      else "ROOT"
00059 
00060     std::string el_identifier = "ROOT";
00061 
00062     std::string precursor("class ");
00063     size_t index1 = el_message.find(precursor);
00064     if (index1 != std::string::npos) {
00065       size_t index2 = index1 + precursor.length();
00066       size_t index3 = el_message.find_first_of(" :", index2);
00067       if (index3 != std::string::npos) {
00068         size_t substrlen = index3-index2;
00069         el_identifier += "-";
00070         el_identifier += el_message.substr(index2,substrlen);
00071       }
00072     } else {
00073       index1 = el_location.find("::");
00074       if (index1 != std::string::npos) {
00075         el_identifier += "/";
00076         el_identifier += el_location.substr(0, index1);
00077       }
00078     }
00079 
00080   // Intercept some messages and upgrade the severity
00081 
00082       if ((el_location.find("TBranchElement::Fill") != std::string::npos)
00083        && (el_message.find("fill branch") != std::string::npos)
00084        && (el_message.find("address") != std::string::npos)
00085        && (el_message.find("not set") != std::string::npos)) {
00086         el_severity = edm::ELseverityLevel::ELsev_fatal;
00087       }
00088 
00089       if ((el_message.find("Tree branches") != std::string::npos)
00090        && (el_message.find("different numbers of entries") != std::string::npos)) {
00091         el_severity = edm::ELseverityLevel::ELsev_fatal;
00092       }
00093 
00094 
00095   // Intercept some messages and downgrade the severity
00096 
00097       if ((el_message.find("dictionary") != std::string::npos) ||
00098           (el_message.find("already in TClassTable") != std::string::npos) ||
00099           (el_message.find("matrix not positive definite") != std::string::npos) ||
00100           (el_location.find("Fit") != std::string::npos) ||
00101           (el_location.find("TDecompChol::Solve") != std::string::npos) ||
00102           (el_location.find("THistPainter::PaintInit") != std::string::npos) ||
00103           (el_location.find("TGClient::GetFontByName") != std::string::npos) ) {
00104         el_severity = edm::ELseverityLevel::ELsev_info;
00105       }
00106 
00107     if (el_severity == edm::ELseverityLevel::ELsev_info) {
00108       // Don't throw if the message is just informational.
00109       die = false;
00110     } else {
00111       die = true;
00112     }
00113 
00114   // Feed the message to the MessageLogger and let it choose to suppress or not.
00115 
00116   // Root has declared a fatal error.  Throw an EDMException unless the
00117   // message corresponds to a pending signal. In that case, do not throw
00118   // but let the OS deal with the signal in the usual way.
00119     if (die && (el_location != std::string("@SUB=TUnixSystem::DispatchSignals"))) {
00120        std::ostringstream sstr;
00121        sstr << "Fatal Root Error: " << el_location << "\n" << el_message << '\n';
00122        edm::Exception except(edm::errors::FatalRootError, sstr.str());
00123        throw except;
00124     }
00125 
00126     // Currently we get here only for informational messages,
00127     // but we leave the other code in just in case we change
00128     // the criteria for throwing.
00129     if (el_severity == edm::ELseverityLevel::ELsev_fatal) {
00130       edm::LogError("Root_Fatal") << el_location << el_message;
00131     } else if (el_severity == edm::ELseverityLevel::ELsev_severe) {
00132       edm::LogError("Root_Severe") << el_location << el_message;
00133     } else if (el_severity == edm::ELseverityLevel::ELsev_error) {
00134       edm::LogError("Root_Error") << el_location << el_message;
00135     } else if (el_severity == edm::ELseverityLevel::ELsev_warning) {
00136       edm::LogWarning("Root_Warning") << el_location << el_message ;
00137     } else if (el_severity == edm::ELseverityLevel::ELsev_info) {
00138       edm::LogInfo("Root_Information") << el_location << el_message ;
00139     }
00140 
00141   }
00142 }  // end of unnamed namespace
00143 
00144 namespace edm {
00145   namespace service {
00146     InitRootHandlers::InitRootHandlers (ParameterSet const& pset)
00147       : RootHandlers(),
00148         unloadSigHandler_(pset.getUntrackedParameter<bool> ("UnloadRootSigHandler")),
00149         resetErrHandler_(pset.getUntrackedParameter<bool> ("ResetRootErrHandler")),
00150         autoLibraryLoader_(pset.getUntrackedParameter<bool> ("AutoLibraryLoader")) {
00151 
00152       if(unloadSigHandler_) {
00153       // Deactivate all the Root signal handlers and restore the system defaults
00154         gSystem->ResetSignal(kSigChild);
00155         gSystem->ResetSignal(kSigBus);
00156         gSystem->ResetSignal(kSigSegmentationViolation);
00157         gSystem->ResetSignal(kSigIllegalInstruction);
00158         gSystem->ResetSignal(kSigSystem);
00159         gSystem->ResetSignal(kSigPipe);
00160         gSystem->ResetSignal(kSigAlarm);
00161         gSystem->ResetSignal(kSigUrgent);
00162         gSystem->ResetSignal(kSigFloatingException);
00163         gSystem->ResetSignal(kSigWindowChanged);
00164       }
00165 
00166       if(resetErrHandler_) {
00167 
00168       // Replace the Root error handler with one that uses the MessageLogger
00169         SetErrorHandler(RootErrorHandler);
00170       }
00171 
00172       // Enable automatic Root library loading.
00173       if(autoLibraryLoader_) {
00174         RootAutoLibraryLoader::enable();
00175       }
00176 
00177       // Enable Cintex.
00178       ROOT::Cintex::Cintex::Enable();
00179 
00180       // Set ROOT parameters.
00181       TTree::SetMaxTreeSize(kMaxLong64);
00182       TH1::AddDirectory(kFALSE);
00183       G__SetCatchException(0);
00184 
00185       // Set custom streamers
00186       setCacheStreamers();
00187       setTransientStreamers();
00188       setRefCoreStreamer();
00189 
00190       // Load the library containing dictionaries for std:: classes (e.g. std::vector<int>)
00191       if (ROOT::Reflex::Type()== Reflex::Type::ByName("std::vector<std::vector<unsigned int> >")) {
00192          edmplugin::PluginCapabilities::get()->load("LCGReflex/std::vector<std::vector<unsigned int> >");
00193       }
00194     }
00195 
00196     InitRootHandlers::~InitRootHandlers () {
00197       // close all open ROOT files
00198       // We get a new iterator each time,
00199       // because closing a file can invalidate the iterator
00200       while(gROOT->GetListOfFiles()->GetSize()) {
00201         TIter iter(gROOT->GetListOfFiles());
00202         TFile* f = dynamic_cast<TFile*>(iter.Next());
00203         if(f) f->Close();
00204       }
00205     }
00206 
00207     void InitRootHandlers::fillDescriptions(ConfigurationDescriptions& descriptions) {
00208       ParameterSetDescription desc;
00209       desc.setComment("Centralized interface to ROOT.");
00210       desc.addUntracked<bool>("UnloadRootSigHandler", false)
00211           ->setComment("If True, signals are handled by this service, rather than by ROOT.");
00212       desc.addUntracked<bool>("ResetRootErrHandler", true)
00213           ->setComment("If True, ROOT messages (e.g. errors, warnings) are handled by this service, rather than by ROOT.");
00214       desc.addUntracked<bool>("AutoLibraryLoader", true)
00215           ->setComment("If True, enables automatic loading of data dictionaries.");
00216       descriptions.add("InitRootHandlers", desc);
00217     }
00218 
00219     void
00220     InitRootHandlers::disableErrorHandler_() {
00221         SetErrorHandler(DefaultErrorHandler);
00222     }
00223 
00224     void
00225     InitRootHandlers::enableErrorHandler_() {
00226         SetErrorHandler(RootErrorHandler);
00227     }
00228   }  // end of namespace service
00229 }  // end of namespace edm