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 <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>
32
33
35 UnhandledException,
36 "Unhandled '" << name << "' exception has been thrown",
37 ((const char *)name) )
38
41 "Got signal " << signum << " " << name,
42 ((int)signum)
43 ((const char *)name) )
44
45namespace 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 SignalHandler( int signal, const char * sig_name )
60 : signal_( signal ),
61 name_( sig_name )
62 {
63 struct sigaction sa;
64
65 sa.sa_sigaction = action;
66 sigemptyset ( &sa.sa_mask );
67 sa.sa_flags = SA_SIGINFO;
68
69 ::sigaction( signal_, &sa, &old_action_ );
70 }
71
72 ~SignalHandler( )
73 {
74 ::sigaction( signal_, &old_action_, 0 );
75 }
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 void ErrorHandler::SignalHandler::action(int signal, siginfo_t*, void *ucontext) {
93 static bool recursive_invocation = false;
94 if (recursive_invocation) {
95 std::cerr << "Got signal " << signal << " " << handlers[signal]->name_
96 << ", aborting the program ..." << std::endl;
97 ::abort();
98 }
99 recursive_invocation = true;
100
101 ers::SignalCatched ex( ERS_HERE_DEBUG, signal, handlers[signal]->name_.c_str());
102#ifdef __x86_64__
103 if (ex.context().stack_size() > 1) {
104 /* overwrite sigaction with caller's address */
105 ucontext_t *uc = (ucontext_t*) ucontext;
106 const_cast<void**>(ex.context().stack_symbols())[1] = (void*) uc->uc_mcontext.gregs[REG_RIP];
107 }
108#endif
109 ErrorHandler::abort(ex);
110 }
111
112 ErrorHandler::ErrorHandler()
113 {
114 if ( !::getenv( "DUNEDAQ_ERS_NO_SIGNAL_HANDLERS" ) )
115 {
116 handlers[SIGSEGV] = new SignalHandler( SIGSEGV, "Segmentation fault (invalid memory reference)" );
117 handlers[SIGBUS] = new SignalHandler( SIGBUS, "Bus error (bad memory access)" );
118 handlers[SIGILL] = new SignalHandler( SIGILL, "Illegal Instruction" );
119 handlers[SIGFPE] = new SignalHandler( SIGFPE, "Floating point exception" );
120 std::set_terminate( terminate_handler );
121#if __cplusplus < 201703L
122 std::set_unexpected( terminate_handler );
123#endif
124 }
125 }
126
127 ErrorHandler::~ErrorHandler()
128 {
129 std::map<int,SignalHandler*>::iterator it;
130 for( it = handlers.begin(); it != handlers.end(); ++it ) {
131 delete it->second;
132 }
133 }
134
135 void ErrorHandler::terminate_handler()
136 {
137 static bool recursive_invocation = false;
138 if (recursive_invocation) {
139 std::cerr << "Unhandled exception has been thrown, aborting the program ..." << std::endl;
140 ::abort();
141 }
142 recursive_invocation = true;
143
144 try {
145 throw;
146 }
147 catch( ers::Issue & ex ) {
148 ErrorHandler::abort( UnhandledException( ERS_HERE_DEBUG, ex.get_class_name(), ex ) );
149 }
150 catch( std::exception & ex ) {
151 ErrorHandler::abort( UnhandledException( ERS_HERE_DEBUG, "std::exception", ex ) );
152 }
153 catch(...) {
154 ErrorHandler::abort( UnhandledException( ERS_HERE_DEBUG, "unknown" ) );
155 }
156 }
157
158 void ErrorHandler::abort( const ers::Issue & issue )
159 {
160 StandardStreamOutput::println(std::cerr, issue, 13);
161 ::abort();
162 }
163}
164
165std::map<int,ers::ErrorHandler::SignalHandler*> ers::ErrorHandler::handlers;
166
167namespace
168{
169 ers::ErrorHandler __handler__;
170}
SignalCatched
#define ERS_HERE_DEBUG
Base class for any user define issue.
Definition Issue.hpp:80
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:65
static std::ostream & println(std::ostream &out, const Issue &issue, int verbosity)