Line data Source code
1 : /*
2 : * DUNE DAQ modification notice:
3 : * This file has been modified from the original ATLAS ers source for the DUNE DAQ project.
4 : * Fork baseline commit: 8267df82a4f6fe6bf02c4014923eba19eddc4614 (2020-04-14).
5 : * Renamed since fork: yes (from src/ErrorHandler.cxx to src/ErrorHandler.cpp).
6 : *
7 : * Original copyright:
8 : * Copyright (C) 2001-2020 CERN for the benefit of the ATLAS collaboration.
9 : * Licensed under the Apache License, Version 2.0.
10 : */
11 :
12 : /*
13 : * ErrorHandler.cxx
14 : * ers
15 : *
16 : * Created by Serguei Kolos on 02.08.05.
17 : * Copyright 2005 CERN. All rights reserved.
18 : *
19 : */
20 : #include <csignal>
21 : #include <iomanip>
22 : #include <iostream>
23 : #include <map>
24 :
25 : #ifdef ERS_NO_DEBUG
26 : #undef ERS_NO_DEBUG
27 : #endif
28 :
29 : #include <ers/Issue.hpp>
30 : #include <ers/StandardStreamOutput.hpp>
31 : #include <ers/ers.hpp>
32 :
33 78 : ERS_DECLARE_ISSUE(ers, UnhandledException, "Unhandled '" << name << "' exception has been thrown", ((const char*)name))
34 :
35 78 : ERS_DECLARE_ISSUE(ers, SignalCatched, "Got signal " << signum << " " << name, ((int)signum)((const char*)name))
36 :
37 : namespace ers {
38 : class ErrorHandler
39 : {
40 : class SignalHandler
41 : {
42 : int signal_;
43 : std::string name_;
44 : struct sigaction old_action_;
45 :
46 : static void action(int, siginfo_t*, void*);
47 :
48 : public:
49 312 : SignalHandler(int signal, const char* sig_name)
50 312 : : signal_(signal)
51 312 : , name_(sig_name)
52 : {
53 312 : struct sigaction sa;
54 :
55 312 : sa.sa_sigaction = action;
56 312 : sigemptyset(&sa.sa_mask);
57 312 : sa.sa_flags = SA_SIGINFO;
58 :
59 312 : ::sigaction(signal_, &sa, &old_action_);
60 312 : }
61 :
62 312 : ~SignalHandler() { ::sigaction(signal_, &old_action_, 0); }
63 : };
64 :
65 : public:
66 : friend class SignalHandler;
67 :
68 : ErrorHandler();
69 : ~ErrorHandler();
70 :
71 : private:
72 : static void abort(const ers::Issue& issue);
73 : static void terminate_handler();
74 :
75 : static std::map<int, SignalHandler*> handlers;
76 : };
77 :
78 : void
79 0 : ErrorHandler::SignalHandler::action(int signal, siginfo_t*, void* ucontext)
80 : {
81 0 : static bool recursive_invocation = false;
82 0 : if (recursive_invocation) {
83 0 : std::cerr << "Got signal " << signal << " " << handlers[signal]->name_ << ", aborting the program ..." << std::endl;
84 0 : ::abort();
85 : }
86 0 : recursive_invocation = true;
87 :
88 0 : ers::SignalCatched ex(ERS_HERE_DEBUG, signal, handlers[signal]->name_.c_str());
89 : #ifdef __x86_64__
90 0 : if (ex.context().stack_size() > 1) {
91 : /* overwrite sigaction with caller's address */
92 0 : ucontext_t* uc = (ucontext_t*)ucontext;
93 0 : const_cast<void**>(ex.context().stack_symbols())[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
94 : }
95 : #endif
96 0 : ErrorHandler::abort(ex);
97 0 : }
98 :
99 78 : ErrorHandler::ErrorHandler()
100 : {
101 78 : if (!::getenv("DUNEDAQ_ERS_NO_SIGNAL_HANDLERS")) {
102 78 : handlers[SIGSEGV] = new SignalHandler(SIGSEGV, "Segmentation fault (invalid memory reference)");
103 78 : handlers[SIGBUS] = new SignalHandler(SIGBUS, "Bus error (bad memory access)");
104 78 : handlers[SIGILL] = new SignalHandler(SIGILL, "Illegal Instruction");
105 78 : handlers[SIGFPE] = new SignalHandler(SIGFPE, "Floating point exception");
106 78 : std::set_terminate(terminate_handler);
107 : #if __cplusplus < 201703L
108 : std::set_unexpected(terminate_handler);
109 : #endif
110 : }
111 78 : }
112 :
113 78 : ErrorHandler::~ErrorHandler()
114 : {
115 78 : std::map<int, SignalHandler*>::iterator it;
116 390 : for (it = handlers.begin(); it != handlers.end(); ++it) {
117 312 : delete it->second;
118 : }
119 78 : }
120 :
121 : void
122 0 : ErrorHandler::terminate_handler()
123 : {
124 0 : static bool recursive_invocation = false;
125 0 : if (recursive_invocation) {
126 0 : std::cerr << "Unhandled exception has been thrown, aborting the program ..." << std::endl;
127 0 : ::abort();
128 : }
129 0 : recursive_invocation = true;
130 :
131 0 : try {
132 0 : throw;
133 0 : } catch (ers::Issue& ex) {
134 0 : ErrorHandler::abort(UnhandledException(ERS_HERE_DEBUG, ex.get_class_name(), ex));
135 0 : } catch (std::exception& ex) {
136 0 : ErrorHandler::abort(UnhandledException(ERS_HERE_DEBUG, "std::exception", ex));
137 0 : } catch (...) {
138 0 : ErrorHandler::abort(UnhandledException(ERS_HERE_DEBUG, "unknown"));
139 0 : }
140 0 : }
141 :
142 : void
143 0 : ErrorHandler::abort(const ers::Issue& issue)
144 : {
145 0 : StandardStreamOutput::println(std::cerr, issue, 13);
146 0 : ::abort();
147 : }
148 : }
149 :
150 : std::map<int, ers::ErrorHandler::SignalHandler*> ers::ErrorHandler::handlers;
151 :
152 : namespace {
153 : ers::ErrorHandler __handler__;
154 : }
|