DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
ErrorHandler.cpp
Go to the documentation of this file.
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>
31#include <ers/ers.hpp>
32
33ERS_DECLARE_ISSUE(ers, UnhandledException, "Unhandled '" << name << "' exception has been thrown", ((const char*)name))
34
35ERS_DECLARE_ISSUE(ers, SignalCatched, "Got signal " << signum << " " << name, ((int)signum)((const char*)name))
36
37namespace ers {
38class 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 SignalHandler(int signal, const char* sig_name)
50 : signal_(signal)
51 , name_(sig_name)
52 {
53 struct sigaction sa;
54
55 sa.sa_sigaction = action;
56 sigemptyset(&sa.sa_mask);
57 sa.sa_flags = SA_SIGINFO;
58
59 ::sigaction(signal_, &sa, &old_action_);
60 }
61
62 ~SignalHandler() { ::sigaction(signal_, &old_action_, 0); }
63 };
64
65public:
66 friend class SignalHandler;
67
68 ErrorHandler();
69 ~ErrorHandler();
70
71private:
72 static void abort(const ers::Issue& issue);
73 static void terminate_handler();
74
75 static std::map<int, SignalHandler*> handlers;
76};
77
78void
79ErrorHandler::SignalHandler::action(int signal, siginfo_t*, void* ucontext)
80{
81 static bool recursive_invocation = false;
82 if (recursive_invocation) {
83 std::cerr << "Got signal " << signal << " " << handlers[signal]->name_ << ", aborting the program ..." << std::endl;
84 ::abort();
85 }
86 recursive_invocation = true;
87
88 ers::SignalCatched ex(ERS_HERE_DEBUG, signal, handlers[signal]->name_.c_str());
89#ifdef __x86_64__
90 if (ex.context().stack_size() > 1) {
91 /* overwrite sigaction with caller's address */
92 ucontext_t* uc = (ucontext_t*)ucontext;
93 const_cast<void**>(ex.context().stack_symbols())[1] = (void*)uc->uc_mcontext.gregs[REG_RIP];
94 }
95#endif
96 ErrorHandler::abort(ex);
97}
98
99ErrorHandler::ErrorHandler()
100{
101 if (!::getenv("DUNEDAQ_ERS_NO_SIGNAL_HANDLERS")) {
102 handlers[SIGSEGV] = new SignalHandler(SIGSEGV, "Segmentation fault (invalid memory reference)");
103 handlers[SIGBUS] = new SignalHandler(SIGBUS, "Bus error (bad memory access)");
104 handlers[SIGILL] = new SignalHandler(SIGILL, "Illegal Instruction");
105 handlers[SIGFPE] = new SignalHandler(SIGFPE, "Floating point exception");
106 std::set_terminate(terminate_handler);
107#if __cplusplus < 201703L
108 std::set_unexpected(terminate_handler);
109#endif
110 }
111}
112
113ErrorHandler::~ErrorHandler()
114{
115 std::map<int, SignalHandler*>::iterator it;
116 for (it = handlers.begin(); it != handlers.end(); ++it) {
117 delete it->second;
118 }
119}
120
121void
122ErrorHandler::terminate_handler()
123{
124 static bool recursive_invocation = false;
125 if (recursive_invocation) {
126 std::cerr << "Unhandled exception has been thrown, aborting the program ..." << std::endl;
127 ::abort();
128 }
129 recursive_invocation = true;
130
131 try {
132 throw;
133 } catch (ers::Issue& ex) {
134 ErrorHandler::abort(UnhandledException(ERS_HERE_DEBUG, ex.get_class_name(), ex));
135 } catch (std::exception& ex) {
136 ErrorHandler::abort(UnhandledException(ERS_HERE_DEBUG, "std::exception", ex));
137 } catch (...) {
138 ErrorHandler::abort(UnhandledException(ERS_HERE_DEBUG, "unknown"));
139 }
140}
141
142void
143ErrorHandler::abort(const ers::Issue& issue)
144{
145 StandardStreamOutput::println(std::cerr, issue, 13);
146 ::abort();
147}
148}
149
150std::map<int, ers::ErrorHandler::SignalHandler*> ers::ErrorHandler::handlers;
151
152namespace {
153ers::ErrorHandler __handler__;
154}
SignalCatched
#define ERS_HERE_DEBUG
Base class for any user define issue.
Definition Issue.hpp:76
virtual const char * get_class_name() const =0
Get key for class (used for serialisation).
#define ERS_DECLARE_ISSUE(namespace_name, class_name, message_, attributes)
Definition macro.hpp:71