LCOV - code coverage report
Current view: top level - ers/src - ErrorHandler.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 44.6 % 56 25
Test Date: 2026-10-11 15:05:20 Functions: 25.0 % 24 6

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

Generated by: LCOV version 2.0-1