InitRootHandlers.cc
Go to the documentation of this file.
4 #include "canvas_root_io/Streamers/BranchDescriptionStreamer.h"
5 #include "canvas_root_io/Streamers/CacheStreamers.h"
6 #include "canvas_root_io/Streamers/ProductIDStreamer.h"
7 #include "canvas_root_io/Streamers/RefCoreStreamer.h"
8 #include "canvas_root_io/Streamers/TransientStreamer.h"
9 #include "canvas_root_io/Streamers/setPtrVectorBaseStreamer.h"
11 
12 #include "TError.h"
13 #include "TH1.h"
14 #include "TROOT.h"
15 #include "TSystem.h"
16 #include "TTree.h"
17 
18 #include <sstream>
19 #include <string.h>
20 
21 namespace {
22 
23  enum class SeverityLevel { kInfo, kWarning, kError, kSysError, kFatal };
24 
25  void
26  RootErrorHandler(int const level,
27  bool die,
28  char const* location,
29  char const* message)
30  {
31  using mf::ELseverityLevel;
32  auto const npos = std::string::npos;
33 
34  // Translate ROOT severity level to MessageLogger severity level
35 
36  SeverityLevel el_severity{SeverityLevel::kInfo};
37  if (level >= kFatal) {
38  el_severity = SeverityLevel::kFatal;
39  } else if (level >= kSysError) {
40  el_severity = SeverityLevel::kSysError;
41  } else if (level >= kError) {
42  el_severity = SeverityLevel::kError;
43  } else if (level >= kWarning) {
44  el_severity = SeverityLevel::kWarning;
45  }
46 
47  // Adapt C-strings to std::strings
48  // Arrange to report the error location as furnished by Root
49 
50  std::string el_location{"@SUB=?"};
51  if (location != nullptr) {
52  el_location = "@SUB=" + std::string(location);
53  }
54 
55  std::string el_message{"?"};
56  if (message != nullptr) {
57  el_message = message;
58  }
59 
60  // Try to create a meaningful id string using knowledge of ROOT error
61  // messages
62  //
63  // id == "ROOT-ClassName" where ClassName is the affected class
64  // else "ROOT/ClassName" where ClassName is the error-declaring class
65  // else "ROOT"
66 
67  std::string el_identifier{"ROOT"};
68 
69  std::string const precursor{"class "};
70  size_t index1 = el_message.find(precursor);
71  if (index1 != npos) {
72  size_t index2 = index1 + precursor.length();
73  size_t index3 = el_message.find_first_of(" :", index2);
74  if (index3 != npos) {
75  size_t substrlen = index3 - index2;
76  el_identifier += "-";
77  el_identifier += el_message.substr(index2, substrlen);
78  }
79  } else {
80  index1 = el_location.find("::");
81  if (index1 != npos) {
82  el_identifier += "/";
83  el_identifier += el_location.substr(0, index1);
84  }
85  }
86 
87  // Intercept and ignore messages:
88  for (std::string const& s :
89  {"art::Transient<art::ProductRegistry::Transients>",
90  "art::DoNotRecordParents"}) {
91  if (el_message ==
92  (std::string("no dictionary for class ") + s + " is available")) {
93  return;
94  }
95  }
96 
97  // Intercept some messages and upgrade the severity
98  if ((el_location.find("TBranchElement::Fill") != npos) &&
99  (el_message.find("fill branch") != npos) &&
100  (el_message.find("address") != npos) &&
101  (el_message.find("not set") != npos)) {
102  el_severity = SeverityLevel::kFatal;
103  }
104  if ((el_message.find("Tree branches") != npos) &&
105  (el_message.find("different numbers of entries") != npos)) {
106  el_severity = SeverityLevel::kFatal;
107  }
108 
109  // Intercept some messages and downgrade the severity
110  if ((el_message.find("dictionary") != npos) ||
111  (el_message.find("already in TClassTable") != npos) ||
112  (el_message.find("matrix not positive definite") != npos) ||
113  (el_message.find("number of iterations was insufficient") != npos) ||
114  (el_message.find("bad integrand behavior") != npos) ||
115  (el_location.find("Fit") != npos) ||
116  (el_location.find("TDecompChol::Solve") != npos) ||
117  (el_location.find("THistPainter::PaintInit") != npos) ||
118  (el_location.find("TGClient::GetFontByName") != npos)) {
119  el_severity = SeverityLevel::kInfo;
120  }
121 
122  if ((el_location.find("TUnixSystem::SetDisplay") != npos) &&
123  (el_message.find("DISPLAY not set") != npos)) {
124  el_severity = SeverityLevel::kInfo;
125  }
126 
127  if ((el_location.find("TTree::ReadStream") != npos) &&
128  (el_message.find("Ignoring trailing") == 0)) {
129  el_severity = SeverityLevel::kInfo;
130  }
131 
132  if (el_severity == SeverityLevel::kInfo) {
133  // Don't throw if the message is just informational.
134  die = false;
135  } else {
136  die = true;
137  }
138 
139  // Feed the message to the MessageLogger and let it choose to suppress or
140  // not.
141 
142  // Root has declared a fatal error. Throw an exception unless the
143  // message corresponds to a pending signal. In that case, do not
144  // throw but let the OS deal with the signal in the usual way.
145  if (die && (location != std::string("TUnixSystem::DispatchSignals"))) {
146  std::ostringstream sstr;
147  sstr << "Fatal Root Error: " << el_location << "\n" << el_message << '\n';
148  throw art::Exception{art::errors::FatalRootError, sstr.str()};
149  }
150 
151  // Currently we get here only for informational messages,
152  // but we leave the other code in just in case we change
153  // the criteria for throwing.
154  if (el_severity == SeverityLevel::kFatal) {
155  mf::LogError("Root_Fatal") << el_location << el_message;
156  } else if (el_severity == SeverityLevel::kSysError) {
157  mf::LogError("Root_Severe") << el_location << el_message;
158  } else if (el_severity == SeverityLevel::kError) {
159  mf::LogError("Root_Error") << el_location << el_message;
160  } else if (el_severity == SeverityLevel::kWarning) {
161  mf::LogWarning("Root_Warning") << el_location << el_message;
162  } else if (el_severity == SeverityLevel::kInfo) {
163  mf::LogInfo("Root_Information") << el_location << el_message;
164  }
165  }
166 } // namespace
167 
168 namespace art {
169 
170  void
172  {
173  // Deactivate all the Root signal handlers and restore the system defaults
174  gSystem->ResetSignal(kSigChild);
175  gSystem->ResetSignal(kSigBus);
176  gSystem->ResetSignal(kSigSegmentationViolation);
177  gSystem->ResetSignal(kSigIllegalInstruction);
178  gSystem->ResetSignal(kSigSystem);
179  gSystem->ResetSignal(kSigPipe);
180  gSystem->ResetSignal(kSigAlarm);
181  gSystem->ResetSignal(kSigUrgent);
182  gSystem->ResetSignal(kSigFloatingException);
183  gSystem->ResetSignal(kSigWindowChanged);
184  }
185 
186  void
187  setRootErrorHandler(bool const want_custom)
188  {
189  if (want_custom) {
190  SetErrorHandler(RootErrorHandler);
191  } else {
192  SetErrorHandler(DefaultErrorHandler);
193  }
194  }
195 
196  void
198  {
199  // Set ROOT parameters. See note in EventProcessor about when
200  // EnableImplicitMT() should be called.
201  ROOT::EnableThreadSafety();
202  TTree::SetMaxTreeSize(kMaxLong64);
203  TH1::AddDirectory(kFALSE);
204 
205  // Initialize tkeyvfs sqlite3 extension for ROOT.
206  tkeyvfs_init();
207 
208  // Set custom streamers.
209  setCacheStreamers();
210  setProvenanceTransientStreamers();
211  detail::setBranchDescriptionStreamer();
212  detail::setPtrVectorBaseStreamer();
213  configureProductIDStreamer();
214  configureRefCoreStreamer();
215  }
216 
217 } // art
void unloadRootSigHandler()
std::string string
Definition: nybbler.cc:12
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
void RootErrorHandler(int level, bool die, char const *location, char const *message)
int tkeyvfs_init(void)
Definition: tkeyvfs.cc:1768
void setRootErrorHandler(bool const want_custom)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void completeRootHandlers()
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
SeverityLevel
static const double s
Definition: Units.h:99