22 #include "tbb/task_scheduler_observer.h" 23 #include "tbb/concurrent_unordered_set.h" 41 #include "TInterpreter.h" 44 #include "TUnixSystem.h" 46 #include "TVirtualStreamerInfo.h" 48 #include "TClassTable.h" 55 constexpr std::size_t moduleBufferSize = 128;
153 thread_local
bool s_ignoreWarnings =
false;
155 bool s_ignoreEverything =
false;
157 void RootErrorHandlerImpl(
int level,
char const* location,
char const*
message) {
165 if (level >= kFatal) {
166 el_severity = SeverityLevel::kFatal;
167 }
else if (level >= kSysError) {
168 el_severity = SeverityLevel::kSysError;
169 }
else if (level >=
kError) {
175 if(s_ignoreEverything) {
186 if (message !=
nullptr) el_message =
message;
197 size_t index1 = el_message.find(precursor);
198 if (index1 != std::string::npos) {
199 size_t index2 = index1 + precursor.length();
200 size_t index3 = el_message.find_first_of(
" :", index2);
201 if (index3 != std::string::npos) {
202 size_t substrlen = index3-index2;
203 el_identifier +=
"-";
204 el_identifier += el_message.substr(index2,substrlen);
207 index1 = el_location.find(
"::");
208 if (index1 != std::string::npos) {
209 el_identifier +=
"/";
210 el_identifier += el_location.substr(0, index1);
216 if ((el_location.find(
"TBranchElement::Fill") != std::string::npos)
217 && (el_message.find(
"fill branch") != std::string::npos)
218 && (el_message.find(
"address") != std::string::npos)
219 && (el_message.find(
"not set") != std::string::npos)) {
220 el_severity = SeverityLevel::kFatal;
223 if ((el_message.find(
"Tree branches") != std::string::npos)
224 && (el_message.find(
"different numbers of entries") != std::string::npos)) {
225 el_severity = SeverityLevel::kFatal;
231 if ((el_message.find(
"no dictionary for class") != std::string::npos) ||
232 (el_message.find(
"already in TClassTable") != std::string::npos) ||
233 (el_message.find(
"matrix not positive definite") != std::string::npos) ||
234 (el_message.find(
"not a TStreamerInfo object") != std::string::npos) ||
235 (el_message.find(
"Problems declaring payload") != std::string::npos) ||
236 (el_message.find(
"Announced number of args different from the real number of argument passed") != std::string::npos) ||
237 (el_location.find(
"Fit") != std::string::npos) ||
238 (el_location.find(
"TDecompChol::Solve") != std::string::npos) ||
239 (el_location.find(
"THistPainter::PaintInit") != std::string::npos) ||
240 (el_location.find(
"TUnixSystem::SetDisplay") != std::string::npos) ||
241 (el_location.find(
"TGClient::GetFontByName") != std::string::npos) ||
242 (el_location.find(
"Inverter::Dinv") != std::string::npos) ||
243 (el_message.find(
"nbins is <=0 - set to nbins = 1") != std::string::npos) ||
244 (el_message.find(
"nbinsy is <=0 - set to nbinsy = 1") != std::string::npos) ||
246 (el_location.find(
"CINTTypedefBuilder::Setup")!= std::string::npos) and
247 (el_message.find(
"possible entries are in use!") != std::string::npos))) {
253 bool alreadyPrinted =
false;
254 if ((el_message.find(
"number of iterations was insufficient") != std::string::npos) ||
255 (el_message.find(
"bad integrand behavior") != std::string::npos) ||
256 (el_message.find(
"integral is divergent, or slowly convergent") != std::string::npos)) {
259 alreadyPrinted =
true;
274 if (die && (el_location !=
std::string(
"@SUB=TUnixSystem::DispatchSignals"))) {
275 std::ostringstream sstr;
276 sstr <<
"Fatal Root Error: " << el_location <<
"\n" << el_message <<
'\n';
279 except.clearMessage();
287 if (!alreadyPrinted) {
288 if (el_severity == SeverityLevel::kFatal) {
290 }
else if (el_severity == SeverityLevel::kSysError) {
297 edm::LogInfo(
"Root_Information") << el_location << el_message ;
302 void RootErrorHandler(
int level,
bool,
char const* location,
char const* message) {
303 RootErrorHandlerImpl(level, location, message);
307 void set_default_signals() {
308 signal(SIGILL, SIG_DFL);
309 signal(SIGSEGV, SIG_DFL);
310 signal(SIGBUS, SIG_DFL);
311 signal(SIGTERM, SIG_DFL);
312 signal(SIGABRT, SIG_DFL);
315 static int full_write(
int fd,
const char *
text)
318 size_t count = strlen(text);
322 written =
write(fd, buffer, count);
325 if (errno == EINTR) {
continue;}
326 else {
return -errno;}
334 static int full_read(
int fd,
char *inbuf,
size_t len,
int timeout_s=-1)
338 ssize_t complete = 0;
345 else if ((-1 == (flags = fcntl(fd, F_GETFL))))
351 if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK))
360 struct pollfd poll_info{fd, POLLIN, 0};
362 if (ms_remaining > 0)
364 int rc = poll(&poll_info, 1, ms_remaining);
368 if (errno == EINTR || errno == EAGAIN) {
continue; }
373 if ((flags & O_NONBLOCK) != O_NONBLOCK)
375 fcntl(fd, F_SETFL, flags);
380 else if (ms_remaining < 0)
382 if ((flags & O_NONBLOCK) != O_NONBLOCK)
384 fcntl(fd, F_SETFL, flags);
389 complete = read(fd, buf, count);
392 if (errno == EINTR) {
continue;}
393 else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
continue;}
396 int orig_errno = errno;
397 if ((flags & O_NONBLOCK) != O_NONBLOCK)
399 fcntl(fd, F_SETFL, flags);
407 if ((flags & O_NONBLOCK) != O_NONBLOCK) {
408 fcntl(fd, F_SETFL, flags);
413 static int full_cerr_write(
const char *text)
415 return full_write(2, text);
422 #if defined(SIGRTMAX) 423 #define PAUSE_SIGNAL SIGRTMAX 424 #define RESUME_SIGNAL SIGRTMAX-1 425 #elif defined(SIGINFO) // macOS/BSD 426 #define PAUSE_SIGNAL SIGINFO 427 #define RESUME_SIGNAL SIGALRM 431 void sig_resume_handler(
int sig, siginfo_t*,
void*) {}
434 void sig_pause_for_stacktrace(
int sig, siginfo_t*,
void*) {
439 sigemptyset(&sigset);
440 sigaddset(&sigset, RESUME_SIGNAL);
441 pthread_sigmask(SIG_UNBLOCK, &sigset,
nullptr);
451 strlcpy(buff,
"\nModule: ", moduleBufferSize);
454 strlcat(buff,
":", moduleBufferSize);
457 strlcat(buff,
"none", moduleBufferSize);
464 void sig_dostack_then_abort(
int sig, siginfo_t*,
void*) {
469 const auto self = pthread_self();
473 struct sigaction act;
474 act.sa_sigaction = sig_pause_for_stacktrace;
476 sigemptyset(&act.sa_mask);
477 sigaction(PAUSE_SIGNAL, &act,
nullptr);
480 sigset_t pausesigset;
481 sigemptyset(&pausesigset);
482 sigaddset(&pausesigset, PAUSE_SIGNAL);
483 sigprocmask(SIG_UNBLOCK, &pausesigset,
nullptr);
486 for (
auto id : tids) {
488 pthread_kill(
id, PAUSE_SIGNAL);
494 act.sa_sigaction = sig_resume_handler;
495 sigaction(RESUME_SIGNAL, &act,
nullptr);
500 const char* signalname =
"unknown";
504 signalname =
"bus error";
509 signalname =
"segmentation violation";
514 signalname =
"illegal instruction";
519 signalname =
"external termination request";
524 signalname =
"abort signal";
530 full_cerr_write(
"\n\nA fatal system signal has occurred: ");
531 full_cerr_write(signalname);
532 full_cerr_write(
"\nThe following is the call stack containing the origin of the signal.\n\n");
541 std::size_t notified = 0;
543 for (
auto id : tids) {
545 if (pthread_kill(
id, RESUME_SIGNAL) == 0) ++notified;
551 full_cerr_write(
"\nCurrent Modules:\n");
558 if (tids.count(
self) > 0) {
559 char buff[moduleBufferSize] =
"\nModule: ";
562 strlcat(buff,
":", moduleBufferSize);
565 strlcat(buff,
"none", moduleBufferSize);
567 strlcat(buff,
" (crashed)", moduleBufferSize);
568 full_cerr_write(buff);
570 full_cerr_write(
"\nModule: non-CMSSW (crashed)");
578 timespec
t = { 0, 1000 };
586 full_cerr_write(
"\n\nA fatal system signal has occurred: ");
587 full_cerr_write(signalname);
588 full_cerr_write(
"\n");
592 if ((sig == SIGILL) || (sig == SIGSEGV) || (sig == SIGBUS) || (sig == SIGTERM) || (sig == SIGABRT))
594 signal(sig, SIG_DFL);
599 set_default_signals();
604 void sig_abort(
int sig, siginfo_t*,
void*) {
605 full_cerr_write(
"\n\nFatal system signal has occurred during exit\n");
608 signal(sig, SIG_DFL);
612 set_default_signals();
634 char buf[2]; buf[1] =
'\0';
638 int result = full_read(fromParent, buf, 1);
644 set_default_signals();
646 full_cerr_write(
"\n\nTraceback helper thread failed to read from parent: ");
647 full_cerr_write(strerror(-result));
648 full_cerr_write(
"\n");
653 set_default_signals();
655 full_write(toParent, buf);
657 else if (buf[0] ==
'2')
666 else if (buf[0] ==
'3')
672 set_default_signals();
674 full_cerr_write(
"\n\nTraceback helper thread got unknown command from parent: ");
675 full_cerr_write(buf);
676 full_cerr_write(
"\n");
687 full_cerr_write(
"\n\nAttempt to request stacktrace failed: ");
688 full_cerr_write(strerror(-result));
689 full_cerr_write(
"\n");
692 char buf[2]; buf[1] =
'\0';
695 full_cerr_write(
"\n\nWaiting for stacktrace completion failed: ");
696 if (result == -ETIMEDOUT)
698 full_cerr_write(
"timed out waiting for GDB to complete.");
702 full_cerr_write(strerror(-result));
704 full_cerr_write(
"\n");
711 char child_stack[4*1024];
712 char *child_stack_ptr = child_stack + 4*1024;
722 if (child_stack_ptr) {}
727 full_cerr_write(
"(Attempt to perform stack dump failed.)\n");
732 if (waitpid(pid, &status, 0) == -1)
734 full_cerr_write(
"(Failed to wait on stack dump output.)\n");
738 full_cerr_write(
"(GDB stack trace failed unexpectedly)\n");
745 set_default_signals();
752 syscall(SYS_execve,
"/bin/sh", argv, __environ);
754 execv(
"/bin/sh", argv);
784 gSystem->ResetSignal(kSigChild);
785 gSystem->ResetSignal(kSigBus);
786 gSystem->ResetSignal(kSigSegmentationViolation);
787 gSystem->ResetSignal(kSigIllegalInstruction);
788 gSystem->ResetSignal(kSigSystem);
789 gSystem->ResetSignal(kSigPipe);
790 gSystem->ResetSignal(kSigAlarm);
791 gSystem->ResetSignal(kSigUrgent);
792 gSystem->ResetSignal(kSigFloatingException);
793 gSystem->ResetSignal(kSigWindowChanged);
799 gSystem->ResetSignal(kSigBus);
800 gSystem->ResetSignal(kSigSegmentationViolation);
801 gSystem->ResetSignal(kSigIllegalInstruction);
820 signal(SIGABRT,SIG_DFL);
833 SetErrorHandler(RootErrorHandler);
838 gInterpreter->SetClassAutoloading(1);
842 TTree::SetMaxTreeSize(kMaxLong64);
843 TH1::AddDirectory(kFALSE);
850 if (!
hasDictionary(
typeid(std::vector<std::vector<unsigned int> >))) {
861 if (imt && not ROOT::IsImplicitMTEnabled()) {
862 ROOT::EnableImplicitMT();
868 TIter iter(gROOT->GetListOfFiles());
869 TObject *
obj =
nullptr;
870 while(
nullptr != (obj = iter.Next())) {
871 TFile*
f =
dynamic_cast<TFile*
>(
obj);
876 iter = TIter(gROOT->GetListOfFiles());
883 ROOT::EnableThreadSafety();
886 TObject::SetObjectStat(
false);
889 TVirtualStreamerInfo::Optimize(
false);
894 desc.
setComment(
"Centralized interface to ROOT.");
896 ->setComment(
"If True, signals are handled by this service, rather than by ROOT.");
898 ->setComment(
"If True, ROOT messages (e.g. errors, warnings) are handled by this service, rather than by ROOT.");
900 ->setComment(
"If True, enables automatic loading of data dictionaries.");
902 ->setComment(
"If True, loads all ROOT dictionaries.");
904 ->setComment(
"If True, calls ROOT::EnableImplicitMT().");
906 ->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.");
908 ->setComment(
"Sets ROOT's gDebug value.");
910 ->setComment(
"Seconds to pause other threads during stack trace.");
911 descriptions.
add(
"InitRootHandlers", desc);
921 s_ignoreWarnings =
false;
926 s_ignoreWarnings =
true;
941 "set pagination no\n" 942 "thread apply all bt\n" 944 "/bin/sed -n -e 's/^\\((gdb) \\)*//' -e '/^#/p' -e '/^Thread/p'", getpid()) >=
pidStringLength_)
946 std::ostringstream sstr;
947 sstr <<
"Unable to pre-allocate stacktrace handler information";
964 std::ostringstream sstr;
965 sstr <<
"Failed to create child-to-parent pipes (errno=" << errno <<
"): " << strerror(errno);
974 std::ostringstream sstr;
975 sstr <<
"Failed to create child-to-parent pipes (errno=" << errno <<
"): " << strerror(errno);
unsigned int maxNumberOfThreads() const
T getUntrackedParameter(std::string const &, T const &) const
bool loadAllDictionaries_
void enableWarnings_() override
static void cmssw_stacktrace_fork()
#define DEFINE_FWK_SERVICE_MAKER(concrete, maker)
void watchPreallocate(Preallocate::slot_type const &iSlot)
void setRefCoreStreamerInTClass()
static void stacktraceFromThread()
static char *const pstackArgv_[]
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
Container_type threadIDs_
bool isProcessWideService(TFileService const *)
static ModuleCallingContext const * getCurrentModuleOnThread()
std::vector< Variable::Flags > flags
static int stackTracePause_
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)
static std::atomic< std::size_t > doneModules_
static const ThreadTracker::Container_type & threadIDs()
std::shared_ptr< const void > sigAbrtHandler_
void setComment(std::string const &value)
std::string moduleName(Provenance const &provenance)
static std::atomic< std::size_t > nextModule_
static char pidString_[pidStringLength_]
static ThreadTracker threadTracker_
edm::serviceregistry::AllArgsMaker< edm::RootHandlers, InitRootHandlers > RootHandlersMaker
static char *const * getPstackArgv()
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::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
std::shared_ptr< const void > sigIllHandler_
void ignoreWarnings_() override
static int childToParent_[2]
std::shared_ptr< const void > sigTermHandler_
void addAdditionalInfo(std::string const &info)
int cmssw_stacktrace(void *)
static std::unique_ptr< std::thread > helperThread_
static std::vector< std::array< char, moduleBufferSize > > moduleListBuffers_
InitRootHandlers(ParameterSet const &pset, ActivityRegistry &iReg)
tbb::concurrent_unordered_set< pthread_t > Container_type
void add(std::string const &label, ParameterSetDescription const &psetDescription)
TEveGeoShape * clone(const TEveElement *element, TEveElement *parent)
static int parentToChild_[2]
void willBeUsingThreads() override
char data[epos_bytes_allocation]
static void fillDescriptions(ConfigurationDescriptions &descriptions)
~InitRootHandlers() override
static const int pidStringLength_
const Container_type & IDs()
static int stackTracePause()
static void stacktraceHelperThread()
bool hasDictionary(std::type_info const &)
void on_scheduler_entry(bool) override