22 #include "tbb/task_scheduler_observer.h" 23 #include "tbb/concurrent_unordered_set.h" 45 #include "TInterpreter.h" 48 #include "TUnixSystem.h" 50 #include "TVirtualStreamerInfo.h" 52 #include "TClassTable.h" 59 constexpr std::size_t moduleBufferSize = 128;
151 bool s_ignoreEverything =
false;
153 template<std::
size_t SIZE>
154 bool find_if_string(
const std::string&
search,
const std::array<const char* const,SIZE>& substrs){
155 return (std::find_if(substrs.begin(), substrs.end(), [&
search](
const char*
const s) ->
bool {
return (search.find(
s) != std::string::npos); }) != substrs.end());
158 constexpr std::array<const char* const,8> in_message{{
159 "no dictionary for class",
160 "already in TClassTable",
161 "matrix not positive definite",
162 "not a TStreamerInfo object",
163 "Problems declaring payload",
164 "Announced number of args different from the real number of argument passed",
165 "nbins is <=0 - set to nbins = 1",
166 "nbinsy is <=0 - set to nbinsy = 1" 169 constexpr std::array<const char* const,6> in_location{{
171 "TDecompChol::Solve",
172 "THistPainter::PaintInit",
173 "TUnixSystem::SetDisplay",
174 "TGClient::GetFontByName",
178 constexpr std::array<const char* const,3> in_message_print{{
179 "number of iterations was insufficient",
180 "bad integrand behavior",
181 "integral is divergent, or slowly convergent" 184 void RootErrorHandlerImpl(
int level,
char const* location,
char const* message) {
192 if (level >= kFatal) {
194 }
else if (level >= kSysError) {
196 }
else if (level >= kError) {
198 }
else if (level >= kWarning) {
202 if (s_ignoreEverything || el_severity <= s_ignoreWarnings) {
213 if (message !=
nullptr) el_message = message;
224 size_t index1 = el_message.find(precursor);
225 if (index1 != std::string::npos) {
226 size_t index2 = index1 + precursor.length();
227 size_t index3 = el_message.find_first_of(
" :", index2);
228 if (index3 != std::string::npos) {
229 size_t substrlen = index3-index2;
230 el_identifier +=
"-";
231 el_identifier += el_message.substr(index2,substrlen);
234 index1 = el_location.find(
"::");
235 if (index1 != std::string::npos) {
236 el_identifier +=
"/";
237 el_identifier += el_location.substr(0, index1);
243 if ((el_location.find(
"TBranchElement::Fill") != std::string::npos)
244 && (el_message.find(
"fill branch") != std::string::npos)
245 && (el_message.find(
"address") != std::string::npos)
246 && (el_message.find(
"not set") != std::string::npos)) {
250 if ((el_message.find(
"Tree branches") != std::string::npos)
251 && (el_message.find(
"different numbers of entries") != std::string::npos)) {
258 if (find_if_string(el_message,in_message) ||
259 find_if_string(el_location,in_location) ||
260 (level < kError and (el_location.find(
"CINTTypedefBuilder::Setup")!= std::string::npos) and (el_message.find(
"possible entries are in use!") != std::string::npos)))
267 bool alreadyPrinted =
false;
268 if (find_if_string(el_message,in_message_print))
272 alreadyPrinted =
true;
287 if (die && (el_location !=
std::string(
"@SUB=TUnixSystem::DispatchSignals"))) {
288 std::ostringstream sstr;
289 sstr <<
"Fatal Root Error: " << el_location <<
"\n" << el_message <<
'\n';
292 except.clearMessage();
300 if (!alreadyPrinted) {
310 edm::LogInfo(
"Root_Information") << el_location << el_message ;
315 void RootErrorHandler(
int level,
bool,
char const* location,
char const* message) {
316 RootErrorHandlerImpl(level, location, message);
320 void set_default_signals() {
321 signal(SIGILL, SIG_DFL);
322 signal(SIGSEGV, SIG_DFL);
323 signal(SIGBUS, SIG_DFL);
324 signal(SIGTERM, SIG_DFL);
325 signal(SIGABRT, SIG_DFL);
328 static int full_write(
int fd,
const char *
text)
331 size_t count = strlen(text);
335 written =
write(fd, buffer, count);
338 if (errno == EINTR) {
continue;}
339 else {
return -errno;}
347 static int full_read(
int fd,
char *inbuf,
size_t len,
int timeout_s=-1)
351 ssize_t complete = 0;
358 else if ((-1 == (flags = fcntl(fd, F_GETFL))))
364 if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK))
373 struct pollfd poll_info{fd, POLLIN, 0};
375 if (ms_remaining > 0)
377 int rc = poll(&poll_info, 1, ms_remaining);
381 if (errno == EINTR || errno == EAGAIN) {
continue; }
386 if ((flags & O_NONBLOCK) != O_NONBLOCK)
388 fcntl(fd, F_SETFL, flags);
393 else if (ms_remaining < 0)
395 if ((flags & O_NONBLOCK) != O_NONBLOCK)
397 fcntl(fd, F_SETFL, flags);
402 complete = read(fd, buf, count);
405 if (errno == EINTR) {
continue;}
406 else if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
continue;}
409 int orig_errno = errno;
410 if ((flags & O_NONBLOCK) != O_NONBLOCK)
412 fcntl(fd, F_SETFL, flags);
420 if ((flags & O_NONBLOCK) != O_NONBLOCK) {
421 fcntl(fd, F_SETFL, flags);
426 static int full_cerr_write(
const char *text)
428 return full_write(2, text);
435 #if defined(SIGRTMAX) 436 #define PAUSE_SIGNAL SIGRTMAX 437 #define RESUME_SIGNAL SIGRTMAX-1 438 #elif defined(SIGINFO) // macOS/BSD 439 #define PAUSE_SIGNAL SIGINFO 440 #define RESUME_SIGNAL SIGALRM 444 void sig_resume_handler(
int sig, siginfo_t*,
void*) {}
447 void sig_pause_for_stacktrace(
int sig, siginfo_t*,
void*) {
452 sigemptyset(&sigset);
453 sigaddset(&sigset, RESUME_SIGNAL);
454 pthread_sigmask(SIG_UNBLOCK, &sigset,
nullptr);
464 strlcpy(buff,
"\nModule: ", moduleBufferSize);
467 strlcat(buff,
":", moduleBufferSize);
470 strlcat(buff,
"none", moduleBufferSize);
477 void sig_dostack_then_abort(
int sig, siginfo_t*,
void*) {
482 const auto self = pthread_self();
486 struct sigaction act;
487 act.sa_sigaction = sig_pause_for_stacktrace;
489 sigemptyset(&act.sa_mask);
490 sigaction(PAUSE_SIGNAL, &act,
nullptr);
493 sigset_t pausesigset;
494 sigemptyset(&pausesigset);
495 sigaddset(&pausesigset, PAUSE_SIGNAL);
496 sigprocmask(SIG_UNBLOCK, &pausesigset,
nullptr);
499 for (
auto id : tids) {
501 pthread_kill(
id, PAUSE_SIGNAL);
507 act.sa_sigaction = sig_resume_handler;
508 sigaction(RESUME_SIGNAL, &act,
nullptr);
513 const char* signalname =
"unknown";
517 signalname =
"bus error";
522 signalname =
"segmentation violation";
527 signalname =
"illegal instruction";
532 signalname =
"external termination request";
537 signalname =
"abort signal";
543 full_cerr_write(
"\n\nA fatal system signal has occurred: ");
544 full_cerr_write(signalname);
545 full_cerr_write(
"\nThe following is the call stack containing the origin of the signal.\n\n");
554 std::size_t notified = 0;
556 for (
auto id : tids) {
558 if (pthread_kill(
id, RESUME_SIGNAL) == 0) ++notified;
564 full_cerr_write(
"\nCurrent Modules:\n");
571 if (tids.count(
self) > 0) {
572 char buff[moduleBufferSize] =
"\nModule: ";
575 strlcat(buff,
":", moduleBufferSize);
578 strlcat(buff,
"none", moduleBufferSize);
580 strlcat(buff,
" (crashed)", moduleBufferSize);
581 full_cerr_write(buff);
583 full_cerr_write(
"\nModule: non-CMSSW (crashed)");
591 timespec
t = { 0, 1000 };
599 full_cerr_write(
"\n\nA fatal system signal has occurred: ");
600 full_cerr_write(signalname);
601 full_cerr_write(
"\n");
605 if ((sig == SIGILL) || (sig == SIGSEGV) || (sig == SIGBUS) || (sig == SIGTERM) || (sig == SIGABRT))
607 signal(sig, SIG_DFL);
612 set_default_signals();
617 void sig_abort(
int sig, siginfo_t*,
void*) {
618 full_cerr_write(
"\n\nFatal system signal has occurred during exit\n");
621 signal(sig, SIG_DFL);
625 set_default_signals();
647 char buf[2]; buf[1] =
'\0';
651 int result = full_read(fromParent, buf, 1);
657 set_default_signals();
659 full_cerr_write(
"\n\nTraceback helper thread failed to read from parent: ");
660 full_cerr_write(strerror(-result));
661 full_cerr_write(
"\n");
666 set_default_signals();
668 full_write(toParent, buf);
670 else if (buf[0] ==
'2')
679 else if (buf[0] ==
'3')
685 set_default_signals();
687 full_cerr_write(
"\n\nTraceback helper thread got unknown command from parent: ");
688 full_cerr_write(buf);
689 full_cerr_write(
"\n");
700 full_cerr_write(
"\n\nAttempt to request stacktrace failed: ");
701 full_cerr_write(strerror(-result));
702 full_cerr_write(
"\n");
705 char buf[2]; buf[1] =
'\0';
708 full_cerr_write(
"\n\nWaiting for stacktrace completion failed: ");
709 if (result == -ETIMEDOUT)
711 full_cerr_write(
"timed out waiting for GDB to complete.");
715 full_cerr_write(strerror(-result));
717 full_cerr_write(
"\n");
724 char child_stack[4*1024];
725 char *child_stack_ptr = child_stack + 4*1024;
735 if (child_stack_ptr) {}
740 full_cerr_write(
"(Attempt to perform stack dump failed.)\n");
745 if (waitpid(pid, &status, 0) == -1)
747 full_cerr_write(
"(Failed to wait on stack dump output.)\n");
751 full_cerr_write(
"(GDB stack trace failed unexpectedly)\n");
758 set_default_signals();
765 syscall(SYS_execve,
"/bin/sh", argv, __environ);
767 execv(
"/bin/sh", argv);
797 gSystem->ResetSignal(kSigChild);
798 gSystem->ResetSignal(kSigBus);
799 gSystem->ResetSignal(kSigSegmentationViolation);
800 gSystem->ResetSignal(kSigIllegalInstruction);
801 gSystem->ResetSignal(kSigSystem);
802 gSystem->ResetSignal(kSigPipe);
803 gSystem->ResetSignal(kSigAlarm);
804 gSystem->ResetSignal(kSigUrgent);
805 gSystem->ResetSignal(kSigFloatingException);
806 gSystem->ResetSignal(kSigWindowChanged);
812 gSystem->ResetSignal(kSigBus);
813 gSystem->ResetSignal(kSigSegmentationViolation);
814 gSystem->ResetSignal(kSigIllegalInstruction);
833 signal(SIGABRT,SIG_DFL);
846 SetErrorHandler(RootErrorHandler);
851 gInterpreter->SetClassAutoloading(1);
855 TTree::SetMaxTreeSize(kMaxLong64);
856 TH1::AddDirectory(kFALSE);
863 if (!
hasDictionary(
typeid(std::vector<std::vector<unsigned int> >))) {
874 if (imt && not ROOT::IsImplicitMTEnabled()) {
875 ROOT::EnableImplicitMT();
881 TIter iter(gROOT->GetListOfFiles());
882 TObject *
obj =
nullptr;
883 while(
nullptr != (obj = iter.Next())) {
884 TFile*
f =
dynamic_cast<TFile*
>(
obj);
889 iter = TIter(gROOT->GetListOfFiles());
896 ROOT::EnableThreadSafety();
899 TObject::SetObjectStat(
false);
902 TVirtualStreamerInfo::Optimize(
false);
907 desc.
setComment(
"Centralized interface to ROOT.");
909 ->setComment(
"If True, signals are handled by this service, rather than by ROOT.");
911 ->setComment(
"If True, ROOT messages (e.g. errors, warnings) are handled by this service, rather than by ROOT.");
913 ->setComment(
"If True, enables automatic loading of data dictionaries.");
915 ->setComment(
"If True, loads all ROOT dictionaries.");
917 ->setComment(
"If True, calls ROOT::EnableImplicitMT().");
919 ->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.");
921 ->setComment(
"Sets ROOT's gDebug value.");
923 ->setComment(
"Seconds to pause other threads during stack trace.");
924 descriptions.
add(
"InitRootHandlers", desc);
939 s_ignoreWarnings =
level;
954 "set pagination no\n" 955 "thread apply all bt\n" 957 "/bin/sed -n -e 's/^\\((gdb) \\)*//' -e '/^#/p' -e '/^Thread/p'", getpid()) >=
pidStringLength_)
959 std::ostringstream sstr;
960 sstr <<
"Unable to pre-allocate stacktrace handler information";
977 std::ostringstream sstr;
978 sstr <<
"Failed to create child-to-parent pipes (errno=" << errno <<
"): " << strerror(errno);
987 std::ostringstream sstr;
988 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_
std::vector< T >::const_iterator search(const cond::Time_t &val, const std::vector< T > &container)
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 *)
void ignoreWarnings_(edm::RootHandlers::SeverityLevel level) override
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_
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