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