CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
InitRootHandlers.cc
Go to the documentation of this file.
2 
4 
16 
17 #include <thread>
18 #include <sys/wait.h>
19 #include <sstream>
20 #include <string.h>
21 #include <poll.h>
22 
23 // WORKAROUND: At CERN, execv is replaced with a non-async-signal safe
24 // version. This can break our stack trace printer. Avoid this by
25 // invoking the syscall directly.
26 #ifdef __linux__
27 #include <syscall.h>
28 #endif
29 
30 #include "TROOT.h"
31 #include "TError.h"
32 #include "TFile.h"
33 #include "TInterpreter.h"
34 #include "TH1.h"
35 #include "TSystem.h"
36 #include "TUnixSystem.h"
37 #include "TTree.h"
38 #include "TVirtualStreamerInfo.h"
39 
40 #include "TThread.h"
41 #include "TClassTable.h"
42 
43 #include <memory>
44 
45 namespace edm {
47  class ParameterSet;
48  class ActivityRegistry;
49 
50  namespace service {
51  class InitRootHandlers : public RootHandlers {
52 
53  friend int cmssw_stacktrace(void *);
54 
55  public:
56  explicit InitRootHandlers(ParameterSet const& pset, ActivityRegistry& iReg);
57  virtual ~InitRootHandlers();
58 
59  static void fillDescriptions(ConfigurationDescriptions& descriptions);
60  static void stacktraceFromThread();
61 
62  private:
63  static char *const *getPstackArgv();
64  virtual void enableWarnings_() override;
65  virtual void ignoreWarnings_() override;
66  virtual void willBeUsingThreads() override;
67  virtual void initializeThisThreadForUse() override;
68 
69  void cachePidInfoHandler(unsigned int, unsigned int) {cachePidInfo();}
70  void cachePidInfo();
71  static void stacktraceHelperThread();
72 
73  static const int pidStringLength_ = 200;
75  static char * const pstackArgv_[];
76  static int parentToChild_[2];
77  static int childToParent_[2];
78  static std::unique_ptr<std::thread> helperThread_;
83  std::shared_ptr<const void> sigBusHandler_;
84  std::shared_ptr<const void> sigSegvHandler_;
85  std::shared_ptr<const void> sigIllHandler_;
86  std::shared_ptr<const void> sigTermHandler_;
87  };
88 
89  inline
91  return true;
92  }
93 
94  } // end of namespace service
95 } // end of namespace edm
96 
97 namespace edm {
98  namespace service {
99  int cmssw_stacktrace(void *);
100  }
101 }
102 
103 namespace {
104  enum class SeverityLevel {
105  kInfo,
106  kWarning,
107  kError,
108  kSysError,
109  kFatal
110  };
111 
112  static thread_local bool s_ignoreWarnings = false;
113 
114  static bool s_ignoreEverything = false;
115 
116  void RootErrorHandlerImpl(int level, char const* location, char const* message) {
117 
118  bool die = false;
119 
120  // Translate ROOT severity level to MessageLogger severity level
121 
122  SeverityLevel el_severity = SeverityLevel::kInfo;
123 
124  if (level >= kFatal) {
125  el_severity = SeverityLevel::kFatal;
126  } else if (level >= kSysError) {
127  el_severity = SeverityLevel::kSysError;
128  } else if (level >= kError) {
129  el_severity = SeverityLevel::kError;
130  } else if (level >= kWarning) {
131  el_severity = s_ignoreWarnings ? SeverityLevel::kInfo : SeverityLevel::kWarning;
132  }
133 
134  if(s_ignoreEverything) {
135  el_severity = SeverityLevel::kInfo;
136  }
137 
138  // Adapt C-strings to std::strings
139  // Arrange to report the error location as furnished by Root
140 
141  std::string el_location = "@SUB=?";
142  if (location != 0) el_location = std::string("@SUB=")+std::string(location);
143 
144  std::string el_message = "?";
145  if (message != 0) el_message = message;
146 
147  // Try to create a meaningful id string using knowledge of ROOT error messages
148  //
149  // id == "ROOT-ClassName" where ClassName is the affected class
150  // else "ROOT/ClassName" where ClassName is the error-declaring class
151  // else "ROOT"
152 
153  std::string el_identifier = "ROOT";
154 
155  std::string precursor("class ");
156  size_t index1 = el_message.find(precursor);
157  if (index1 != std::string::npos) {
158  size_t index2 = index1 + precursor.length();
159  size_t index3 = el_message.find_first_of(" :", index2);
160  if (index3 != std::string::npos) {
161  size_t substrlen = index3-index2;
162  el_identifier += "-";
163  el_identifier += el_message.substr(index2,substrlen);
164  }
165  } else {
166  index1 = el_location.find("::");
167  if (index1 != std::string::npos) {
168  el_identifier += "/";
169  el_identifier += el_location.substr(0, index1);
170  }
171  }
172 
173  // Intercept some messages and upgrade the severity
174 
175  if ((el_location.find("TBranchElement::Fill") != std::string::npos)
176  && (el_message.find("fill branch") != std::string::npos)
177  && (el_message.find("address") != std::string::npos)
178  && (el_message.find("not set") != std::string::npos)) {
179  el_severity = SeverityLevel::kFatal;
180  }
181 
182  if ((el_message.find("Tree branches") != std::string::npos)
183  && (el_message.find("different numbers of entries") != std::string::npos)) {
184  el_severity = SeverityLevel::kFatal;
185  }
186 
187 
188  // Intercept some messages and downgrade the severity
189 
190  if ((el_message.find("no dictionary for class") != std::string::npos) ||
191  (el_message.find("already in TClassTable") != std::string::npos) ||
192  (el_message.find("matrix not positive definite") != std::string::npos) ||
193  (el_message.find("not a TStreamerInfo object") != std::string::npos) ||
194  (el_message.find("Problems declaring payload") != std::string::npos) ||
195  (el_message.find("Announced number of args different from the real number of argument passed") != std::string::npos) || // Always printed if gDebug>0 - regardless of whether warning message is real.
196  (el_location.find("Fit") != std::string::npos) ||
197  (el_location.find("TDecompChol::Solve") != std::string::npos) ||
198  (el_location.find("THistPainter::PaintInit") != std::string::npos) ||
199  (el_location.find("TUnixSystem::SetDisplay") != std::string::npos) ||
200  (el_location.find("TGClient::GetFontByName") != std::string::npos) ||
201  (el_message.find("nbins is <=0 - set to nbins = 1") != std::string::npos) ||
202  (el_message.find("nbinsy is <=0 - set to nbinsy = 1") != std::string::npos) ||
203  (level < kError and
204  (el_location.find("CINTTypedefBuilder::Setup")!= std::string::npos) and
205  (el_message.find("possible entries are in use!") != std::string::npos))) {
206  el_severity = SeverityLevel::kInfo;
207  }
208 
209  if (el_severity == SeverityLevel::kInfo) {
210  // Don't throw if the message is just informational.
211  die = false;
212  } else {
213  die = true;
214  }
215 
216  // Feed the message to the MessageLogger and let it choose to suppress or not.
217 
218  // Root has declared a fatal error. Throw an EDMException unless the
219  // message corresponds to a pending signal. In that case, do not throw
220  // but let the OS deal with the signal in the usual way.
221  if (die && (el_location != std::string("@SUB=TUnixSystem::DispatchSignals"))) {
222  std::ostringstream sstr;
223  sstr << "Fatal Root Error: " << el_location << "\n" << el_message << '\n';
224  edm::Exception except(edm::errors::FatalRootError, sstr.str());
225  except.addAdditionalInfo(except.message());
226  except.clearMessage();
227  throw except;
228 
229  }
230 
231  // Typically, we get here only for informational messages,
232  // but we leave the other code in just in case we change
233  // the criteria for throwing.
234  if (el_severity == SeverityLevel::kFatal) {
235  edm::LogError("Root_Fatal") << el_location << el_message;
236  } else if (el_severity == SeverityLevel::kSysError) {
237  edm::LogError("Root_Severe") << el_location << el_message;
238  } else if (el_severity == SeverityLevel::kError) {
239  edm::LogError("Root_Error") << el_location << el_message;
240  } else if (el_severity == SeverityLevel::kWarning) {
241  edm::LogWarning("Root_Warning") << el_location << el_message ;
242  } else if (el_severity == SeverityLevel::kInfo) {
243  edm::LogInfo("Root_Information") << el_location << el_message ;
244  }
245  }
246 
247  void RootErrorHandler(int level, bool, char const* location, char const* message) {
248  RootErrorHandlerImpl(level, location, message);
249  }
250 
251  extern "C" {
252 
253  static int full_write(int fd, const char *text)
254  {
255  const char *buffer = text;
256  size_t count = strlen(text);
257  ssize_t written = 0;
258  while (count)
259  {
260  written = write(fd, buffer, count);
261  if (written == -1)
262  {
263  if (errno == EINTR) {continue;}
264  else {return -errno;}
265  }
266  count -= written;
267  buffer += written;
268  }
269  return 0;
270  }
271 
272  static int full_read(int fd, char *inbuf, size_t len, int timeout_s=-1)
273  {
274  char *buf = inbuf;
275  size_t count = len;
276  ssize_t complete = 0;
277  std::chrono::time_point<std::chrono::steady_clock> end_time = std::chrono::steady_clock::now() + std::chrono::seconds(timeout_s);
278  int flags;
279  if (timeout_s < 0)
280  {
281  flags = O_NONBLOCK; // Prevents us from trying to set / restore flags later.
282  }
283  else if ((-1 == (flags = fcntl(fd, F_GETFL))))
284  {
285  return -errno;
286  }
287  if ((flags & O_NONBLOCK) != O_NONBLOCK)
288  {
289  if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK))
290  {
291  return -errno;
292  }
293  }
294  while (count)
295  {
296  if (timeout_s >= 0)
297  {
298  struct pollfd poll_info{fd, POLLIN, 0};
299  int ms_remaining = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-std::chrono::steady_clock::now()).count();
300  if (ms_remaining > 0)
301  {
302  if (poll(&poll_info, 1, ms_remaining) == 0)
303  {
304  if ((flags & O_NONBLOCK) != O_NONBLOCK)
305  {
306  fcntl(fd, F_SETFL, flags);
307  }
308  return -ETIMEDOUT;
309  }
310  }
311  else if (ms_remaining < 0)
312  {
313  if ((flags & O_NONBLOCK) != O_NONBLOCK)
314  {
315  fcntl(fd, F_SETFL, flags);
316  }
317  return -ETIMEDOUT;
318  }
319  }
320  complete = read(fd, buf, count);
321  if (complete == -1)
322  {
323  if (errno == EINTR) {continue;}
324  else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {continue;}
325  else
326  {
327  int orig_errno = errno;
328  if ((flags & O_NONBLOCK) != O_NONBLOCK)
329  {
330  fcntl(fd, F_SETFL, flags);
331  }
332  return -orig_errno;
333  }
334  }
335  count -= complete;
336  buf += complete;
337  }
338  if ((flags & O_NONBLOCK) != O_NONBLOCK) {
339  fcntl(fd, F_SETFL, flags);
340  }
341  return 0;
342  }
343 
344  static int full_cerr_write(const char *text)
345  {
346  return full_write(2, text);
347  }
348 
349  void sig_dostack_then_abort(int sig, siginfo_t*, void*) {
350 
351  const char* signalname = "unknown";
352  switch (sig) {
353  case SIGBUS:
354  {
355  signalname = "bus error";
356  break;
357  }
358  case SIGSEGV:
359  {
360  signalname = "segmentation violation";
361  break;
362  }
363  case SIGILL:
364  {
365  signalname = "illegal instruction";
366  break;
367  }
368  case SIGTERM:
369  {
370  signalname = "external termination request";
371  break;
372  }
373  default:
374  break;
375  }
376  full_cerr_write("\n\nA fatal system signal has occurred: ");
377  full_cerr_write(signalname);
378  full_cerr_write("\nThe following is the call stack containing the origin of the signal.\n\n");
379 
381 
382  full_cerr_write("\nA fatal system signal has occurred: ");
383  full_cerr_write(signalname);
384  full_cerr_write("\n");
385 
386  // For these four known cases, re-raise the signal so get the correct
387  // exit code.
388  if ((sig == SIGILL) || (sig == SIGSEGV) || (sig == SIGBUS) || (sig == SIGTERM))
389  {
390  signal(sig, SIG_DFL);
391  raise(sig);
392  }
393  else
394  {
395  ::abort();
396  }
397  }
398 
399  void sig_abort(int sig, siginfo_t*, void*) {
400  ::abort();
401  }
402  }
403 
404  void set_default_signals() {
405  signal(SIGILL, SIG_DFL);
406  signal(SIGSEGV, SIG_DFL);
407  signal(SIGBUS, SIG_DFL);
408  signal(SIGTERM, SIG_DFL);
409  }
410 
411 } // end of unnamed namespace
412 
413 namespace edm {
414  namespace service {
415 
416  /*
417  * We've run into issues where GDB fails to print the thread which calls clone().
418  * To avoid this problem, we have an alternate approach below where the signal handler
419  * only reads/writes to a dedicated thread via pipes. The helper thread does the clone()
420  * invocation; we don't care if that thread is missing from the traceback in this case.
421  */
422  static void cmssw_stacktrace_fork();
423 
425  {
426  int toParent = childToParent_[1];
427  int fromParent = parentToChild_[0];
428  char buf[2]; buf[1] = '\0';
429  while(true)
430  {
431  int result = full_read(fromParent, buf, 1);
432  if (result < 0)
433  {
434  // To avoid a deadlock (this function is NOT re-entrant), reset signals
435  // We never set them back to the CMSSW handler because we assume the parent
436  // thread will abort for us.
437  set_default_signals();
438  close(toParent);
439  full_cerr_write("\n\nTraceback helper thread failed to read from parent: ");
440  full_cerr_write(strerror(-result));
441  full_cerr_write("\n");
442  ::abort();
443  }
444  if (buf[0] == '1')
445  {
446  set_default_signals();
448  full_write(toParent, buf);
449  }
450  else if (buf[0] == '2')
451  {
452  // We have just finished forking. Reload the file descriptors for thread
453  // communication.
454  close(toParent);
455  close(fromParent);
456  toParent = childToParent_[1];
457  fromParent = parentToChild_[0];
458  }
459  else if (buf[0] == '3')
460  {
461  break;
462  }
463  else
464  {
465  set_default_signals();
466  close(toParent);
467  full_cerr_write("\n\nTraceback helper thread got unknown command from parent: ");
468  full_cerr_write(buf);
469  full_cerr_write("\n");
470  ::abort();
471  }
472  }
473  }
474 
476  {
477  int result = full_write(parentToChild_[1], "1");
478  if (result < 0)
479  {
480  full_cerr_write("\n\nAttempt to request stacktrace failed: ");
481  full_cerr_write(strerror(-result));
482  full_cerr_write("\n");
483  return;
484  }
485  char buf[2]; buf[1] = '\0';
486  if ((result = full_read(childToParent_[0], buf, 1, 5*60)) < 0)
487  {
488  full_cerr_write("\n\nWaiting for stacktrace completion failed: ");
489  if (result == -ETIMEDOUT)
490  {
491  full_cerr_write("timed out waiting for GDB to complete.");
492  }
493  else
494  {
495  full_cerr_write(strerror(-result));
496  }
497  full_cerr_write("\n");
498  return;
499  }
500  }
501 
503  {
504  char child_stack[4*1024];
505  char *child_stack_ptr = child_stack + 4*1024;
506  // On Linux, we currently use jemalloc. This registers pthread_atfork handlers; these
507  // handlers are *not* async-signal safe. Hence, a deadlock is possible if we invoke
508  // fork() from our signal handlers. Accordingly, we use clone (not POSIX, but AS-safe)
509  // as that is closer to the 'raw metal' syscall and avoids pthread_atfork handlers.
510  int pid =
511 #ifdef __linux__
512  clone(edm::service::cmssw_stacktrace, child_stack_ptr, CLONE_VM|CLONE_FS|SIGCHLD, nullptr);
513 #else
514  fork();
515  if (child_stack_ptr) {} // Suppress 'unused variable' warning on non-Linux
516  if (pid == 0) {edm::service::cmssw_stacktrace(nullptr); ::abort();}
517 #endif
518  if (pid == -1)
519  {
520  full_cerr_write("(Attempt to perform stack dump failed.)\n");
521  }
522  else
523  {
524  int status;
525  if (waitpid(pid, &status, 0) == -1)
526  {
527  full_cerr_write("(Failed to wait on stack dump output.)\n");
528  }
529  if (status)
530  {
531  full_cerr_write("(GDB stack trace failed unexpectedly)\n");
532  }
533  }
534  }
535 
536  int cmssw_stacktrace(void * /*arg*/)
537  {
539  // NOTE: this is NOT async-signal-safe at CERN's lxplus service.
540  // CERN uses LD_PRELOAD to replace execv with a function from libsnoopy which
541  // calls dlsym.
542 #ifdef __linux__
543  syscall(SYS_execve, "/bin/sh", argv, __environ);
544 #else
545  execv("/bin/sh", argv);
546 #endif
547  ::abort();
548  return 1;
549  }
550 
551  static char pstackName[] = "(CMSSW stack trace helper)";
552  static char dashC[] = "-c";
555  int InitRootHandlers::parentToChild_[2] = {-1, -1};
556  int InitRootHandlers::childToParent_[2] = {-1, -1};
557  std::unique_ptr<std::thread> InitRootHandlers::helperThread_;
558 
560  : RootHandlers(),
561  unloadSigHandler_(pset.getUntrackedParameter<bool> ("UnloadRootSigHandler")),
562  resetErrHandler_(pset.getUntrackedParameter<bool> ("ResetRootErrHandler")),
563  loadAllDictionaries_(pset.getUntrackedParameter<bool>("LoadAllDictionaries")),
564  autoLibraryLoader_(loadAllDictionaries_ or pset.getUntrackedParameter<bool> ("AutoLibraryLoader"))
565  {
566 
567  if(unloadSigHandler_) {
568  // Deactivate all the Root signal handlers and restore the system defaults
569  gSystem->ResetSignal(kSigChild);
570  gSystem->ResetSignal(kSigBus);
571  gSystem->ResetSignal(kSigSegmentationViolation);
572  gSystem->ResetSignal(kSigIllegalInstruction);
573  gSystem->ResetSignal(kSigSystem);
574  gSystem->ResetSignal(kSigPipe);
575  gSystem->ResetSignal(kSigAlarm);
576  gSystem->ResetSignal(kSigUrgent);
577  gSystem->ResetSignal(kSigFloatingException);
578  gSystem->ResetSignal(kSigWindowChanged);
579  } else if(pset.getUntrackedParameter<bool>("AbortOnSignal")){
580  cachePidInfo();
581 
582  //NOTE: ROOT can also be told to abort on these kinds of problems BUT
583  // it requires an TApplication to be instantiated which causes problems
584  gSystem->ResetSignal(kSigBus);
585  gSystem->ResetSignal(kSigSegmentationViolation);
586  gSystem->ResetSignal(kSigIllegalInstruction);
587  installCustomHandler(SIGBUS,sig_dostack_then_abort);
588  sigBusHandler_ = std::shared_ptr<const void>(nullptr,[](void*) {
589  installCustomHandler(SIGBUS,sig_abort);
590  });
591  installCustomHandler(SIGSEGV,sig_dostack_then_abort);
592  sigSegvHandler_ = std::shared_ptr<const void>(nullptr,[](void*) {
593  installCustomHandler(SIGSEGV,sig_abort);
594  });
595  installCustomHandler(SIGILL,sig_dostack_then_abort);
596  sigIllHandler_ = std::shared_ptr<const void>(nullptr,[](void*) {
597  installCustomHandler(SIGILL,sig_abort);
598  });
599  installCustomHandler(SIGTERM,sig_dostack_then_abort);
600  sigTermHandler_ = std::shared_ptr<const void>(nullptr,[](void*) {
601  installCustomHandler(SIGTERM,sig_abort);
602  });
604  }
605 
606  if(resetErrHandler_) {
607 
608  // Replace the Root error handler with one that uses the MessageLogger
609  SetErrorHandler(RootErrorHandler);
610  }
611 
612  // Enable automatic Root library loading.
613  if(autoLibraryLoader_) {
614  gInterpreter->SetClassAutoloading(1);
615  }
616 
617  // Set ROOT parameters.
618  TTree::SetMaxTreeSize(kMaxLong64);
619  TH1::AddDirectory(kFALSE);
620  //G__SetCatchException(0);
621 
622  // Set custom streamers
624 
625  // Load the library containing dictionaries for std:: classes, if not already loaded.
626  if (!hasDictionary(typeid(std::vector<std::vector<unsigned int> >))) {
627  TypeWithDict::byName("std::vector<std::vector<unsigned int> >");
628  }
629 
630  int debugLevel = pset.getUntrackedParameter<int>("DebugLevel");
631  if(debugLevel >0) {
632  gDebug = debugLevel;
633  }
634  }
635 
637  // close all open ROOT files
638  TIter iter(gROOT->GetListOfFiles());
639  TObject *obj = nullptr;
640  while(nullptr != (obj = iter.Next())) {
641  TFile* f = dynamic_cast<TFile*>(obj);
642  if(f) {
643  // We get a new iterator each time,
644  // because closing a file can invalidate the iterator
645  f->Close();
646  iter = TIter(gROOT->GetListOfFiles());
647  }
648  }
649  }
650 
652  //Tell Root we want to be multi-threaded
653  TThread::Initialize();
654  //When threading, also have to keep ROOT from logging all TObjects into a list
655  TObject::SetObjectStat(false);
656 
657  //Have to avoid having Streamers modify themselves after they have been used
658  TVirtualStreamerInfo::Optimize(false);
659  }
660 
662  static thread_local TThread guard;
663  }
664 
667  desc.setComment("Centralized interface to ROOT.");
668  desc.addUntracked<bool>("UnloadRootSigHandler", false)
669  ->setComment("If True, signals are handled by this service, rather than by ROOT.");
670  desc.addUntracked<bool>("ResetRootErrHandler", true)
671  ->setComment("If True, ROOT messages (e.g. errors, warnings) are handled by this service, rather than by ROOT.");
672  desc.addUntracked<bool>("AutoLibraryLoader", true)
673  ->setComment("If True, enables automatic loading of data dictionaries.");
674  desc.addUntracked<bool>("LoadAllDictionaries",false)
675  ->setComment("If True, loads all ROOT dictionaries.");
676  desc.addUntracked<bool>("AbortOnSignal",true)
677  ->setComment("If True, do an abort when a signal occurs that causes a crash. If False, ROOT will do an exit which attempts to do a clean shutdown.");
678  desc.addUntracked<int>("DebugLevel",0)
679  ->setComment("Sets ROOT's gDebug value.");
680  descriptions.add("InitRootHandlers", desc);
681  }
682 
683  char *const *
685  return pstackArgv_;
686  }
687 
688  void
690  s_ignoreWarnings =false;
691  }
692 
693  void
695  s_ignoreWarnings = true;
696  }
697 
698  void
700  {
701  if (snprintf(pidString_, pidStringLength_-1, "gdb -quiet -p %d 2>&1 <<EOF |\n"
702  "set width 0\n"
703  "set height 0\n"
704  "set pagination no\n"
705  "thread apply all bt\n"
706  "EOF\n"
707  "/bin/sed -n -e 's/^\\((gdb) \\)*//' -e '/^#/p' -e '/^Thread/p'", getpid()) >= pidStringLength_)
708  {
709  std::ostringstream sstr;
710  sstr << "Unable to pre-allocate stacktrace handler information";
711  edm::Exception except(edm::errors::OtherCMS, sstr.str());
712  throw except;
713  }
714 
715  // These are initialized to -1; harmless to close an invalid FD.
716  // If this is called post-fork, we don't want to be communicating on
717  // these FDs as they are used internally by the parent.
718  close(childToParent_[0]);
719  close(childToParent_[1]);
720  childToParent_[0] = -1; childToParent_[1] = -1;
721  close(parentToChild_[0]);
722  close(parentToChild_[1]);
723  parentToChild_[0] = -1; parentToChild_[1] = -1;
724 
725  if (-1 == pipe2(childToParent_, O_CLOEXEC))
726  {
727  std::ostringstream sstr;
728  sstr << "Failed to create child-to-parent pipes (errno=" << errno << "): " << strerror(errno);
729  edm::Exception except(edm::errors::OtherCMS, sstr.str());
730  throw except;
731  }
732 
733  if (-1 == pipe2(parentToChild_, O_CLOEXEC))
734  {
735  close(childToParent_[0]); close(childToParent_[1]);
736  childToParent_[0] = -1; childToParent_[1] = -1;
737  std::ostringstream sstr;
738  sstr << "Failed to create child-to-parent pipes (errno=" << errno << "): " << strerror(errno);
739  edm::Exception except(edm::errors::OtherCMS, sstr.str());
740  throw except;
741  }
742 
743  helperThread_.reset(new std::thread(stacktraceHelperThread));
744  helperThread_->detach();
745  }
746 
747  } // end of namespace service
748 } // end of namespace edm
749 
753 
T getUntrackedParameter(std::string const &, T const &) const
virtual void enableWarnings_() override
static void cmssw_stacktrace_fork()
#define DEFINE_FWK_SERVICE_MAKER(concrete, maker)
Definition: ServiceMaker.h:117
double seconds()
static char *const pstackArgv_[]
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
bool isProcessWideService(TFileService const *)
Definition: TFileService.h:99
void setRefCoreStreamer(bool resetAll=false)
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
void installCustomHandler(int signum, CFUNC func)
std::shared_ptr< const void > sigSegvHandler_
friend int cmssw_stacktrace(void *)
std::shared_ptr< const void > sigBusHandler_
static TypeWithDict byName(std::string const &name)
Definition: TypeWithDict.cc:60
tuple result
Definition: mps_fire.py:83
void cachePidInfoHandler(unsigned int, unsigned int)
void setComment(std::string const &value)
static char pidString_[pidStringLength_]
edm::serviceregistry::AllArgsMaker< edm::RootHandlers, InitRootHandlers > RootHandlersMaker
static char *const * getPstackArgv()
std::shared_ptr< const void > sigIllHandler_
virtual void initializeThisThreadForUse() override
virtual void ignoreWarnings_() override
std::shared_ptr< const void > sigTermHandler_
tuple fd
Definition: ztee.py:136
void addAdditionalInfo(std::string const &info)
Definition: Exception.cc:235
double f[11][100]
tuple text
Definition: runonSM.py:42
int cmssw_stacktrace(void *)
static std::unique_ptr< std::thread > helperThread_
static char pstackName[]
InitRootHandlers(ParameterSet const &pset, ActivityRegistry &iReg)
tuple pid
Definition: sysUtil.py:22
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TEveGeoShape * clone(const TEveElement *element, TEveElement *parent)
Definition: eve_macros.cc:135
void watchPostForkReacquireResources(PostForkReacquireResources::slot_type const &iSlot)
virtual void willBeUsingThreads() override
static char dashC[]
static void fillDescriptions(ConfigurationDescriptions &descriptions)
SeverityLevel
bool hasDictionary(std::type_info const &)
#define O_NONBLOCK
Definition: SysFile.h:21
tuple level
Definition: testEve_cfg.py:34
tuple status
Definition: mps_update.py:57