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