Line data Source code
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>
20 : #include <ers/StandardStreamOutput.hpp>
21 :
22 :
23 73 : ERS_DECLARE_ISSUE( ers,
24 : UnhandledException,
25 : "Unhandled '" << name << "' exception has been thrown",
26 : ((const char *)name) )
27 :
28 73 : ERS_DECLARE_ISSUE( ers,
29 : SignalCatched,
30 : "Got signal " << signum << " " << name,
31 : ((int)signum)
32 : ((const char *)name) )
33 :
34 : namespace 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 292 : SignalHandler( int signal, const char * sig_name )
49 292 : : signal_( signal ),
50 292 : name_( sig_name )
51 : {
52 292 : struct sigaction sa;
53 :
54 292 : sa.sa_sigaction = action;
55 292 : sigemptyset ( &sa.sa_mask );
56 292 : sa.sa_flags = SA_SIGINFO;
57 :
58 292 : ::sigaction( signal_, &sa, &old_action_ );
59 292 : }
60 :
61 292 : ~SignalHandler( )
62 : {
63 292 : ::sigaction( signal_, &old_action_, 0 );
64 292 : }
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 0 : void ErrorHandler::SignalHandler::action(int signal, siginfo_t*, void *ucontext) {
82 0 : static bool recursive_invocation = false;
83 0 : if (recursive_invocation) {
84 0 : std::cerr << "Got signal " << signal << " " << handlers[signal]->name_
85 0 : << ", aborting the program ..." << std::endl;
86 0 : ::abort();
87 : }
88 0 : recursive_invocation = true;
89 :
90 0 : ers::SignalCatched ex( ERS_HERE_DEBUG, signal, handlers[signal]->name_.c_str());
91 : #ifdef __x86_64__
92 0 : if (ex.context().stack_size() > 1) {
93 : /* overwrite sigaction with caller's address */
94 0 : ucontext_t *uc = (ucontext_t*) ucontext;
95 0 : const_cast<void**>(ex.context().stack_symbols())[1] = (void*) uc->uc_mcontext.gregs[REG_RIP];
96 : }
97 : #endif
98 0 : ErrorHandler::abort(ex);
99 0 : }
100 :
101 73 : ErrorHandler::ErrorHandler()
102 : {
103 73 : if ( !::getenv( "DUNEDAQ_ERS_NO_SIGNAL_HANDLERS" ) )
104 : {
105 73 : handlers[SIGSEGV] = new SignalHandler( SIGSEGV, "Segmentation fault (invalid memory reference)" );
106 73 : handlers[SIGBUS] = new SignalHandler( SIGBUS, "Bus error (bad memory access)" );
107 73 : handlers[SIGILL] = new SignalHandler( SIGILL, "Illegal Instruction" );
108 73 : handlers[SIGFPE] = new SignalHandler( SIGFPE, "Floating point exception" );
109 73 : std::set_terminate( terminate_handler );
110 : #if __cplusplus < 201703L
111 : std::set_unexpected( terminate_handler );
112 : #endif
113 : }
114 73 : }
115 :
116 73 : ErrorHandler::~ErrorHandler()
117 : {
118 73 : std::map<int,SignalHandler*>::iterator it;
119 365 : for( it = handlers.begin(); it != handlers.end(); ++it ) {
120 292 : delete it->second;
121 : }
122 73 : }
123 :
124 0 : void ErrorHandler::terminate_handler()
125 : {
126 0 : static bool recursive_invocation = false;
127 0 : if (recursive_invocation) {
128 0 : std::cerr << "Unhandled exception has been thrown, aborting the program ..." << std::endl;
129 0 : ::abort();
130 : }
131 0 : recursive_invocation = true;
132 :
133 0 : try {
134 0 : throw;
135 : }
136 0 : catch( ers::Issue & ex ) {
137 0 : ErrorHandler::abort( UnhandledException( ERS_HERE_DEBUG, ex.get_class_name(), ex ) );
138 0 : }
139 0 : catch( std::exception & ex ) {
140 0 : ErrorHandler::abort( UnhandledException( ERS_HERE_DEBUG, "std::exception", ex ) );
141 0 : }
142 0 : catch(...) {
143 0 : ErrorHandler::abort( UnhandledException( ERS_HERE_DEBUG, "unknown" ) );
144 0 : }
145 0 : }
146 :
147 0 : void ErrorHandler::abort( const ers::Issue & issue )
148 : {
149 0 : StandardStreamOutput::println(std::cerr, issue, 13);
150 0 : ::abort();
151 : }
152 : }
153 :
154 : std::map<int,ers::ErrorHandler::SignalHandler*> ers::ErrorHandler::handlers;
155 :
156 : namespace
157 : {
158 : ers::ErrorHandler __handler__;
159 : }
|