LCOV - code coverage report
Current view: top level - ers/src - ErrorHandler.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 44.3 % 61 27
Test Date: 2025-12-21 13:07:08 Functions: 25.0 % 24 6

            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              : }
        

Generated by: LCOV version 2.0-1