Xyst test code coverage report
Current view: top level - Base - ProcessException.cpp (source / functions) Hit Total Coverage
Commit: 5689ba12dc66a776d3d75f1ee48cc7d78eaa18dc Lines: 26 43 60.5 %
Date: 2024-11-22 19:17:03 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 10 42 23.8 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Base/ProcessException.cpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.,
       7                 :            :              2022-2024 J. Bakosi
       8                 :            :              All rights reserved. See the LICENSE file for details.
       9                 :            :   \brief     Process an exception
      10                 :            :   \details   This file contains the implementation of processing an exception.
      11                 :            :     Logically, it would make sense to put this into Exception.C, however,
      12                 :            :     Exception.h is included by all who want to be able throw an exception (a
      13                 :            :     potentially large number of files) and that would pull in the charm++.h as
      14                 :            :     well as the mpi.h headers, which triggers a slew of compiler warnings. On
      15                 :            :     the other hand, processing an exception is only done by the executables'
      16                 :            :     main chares objects and a few select explicit main() routines that use MPI,
      17                 :            :     which is a lot less than those which throw, so processing an exception is
      18                 :            :     separated here.
      19                 :            : */
      20                 :            : // *****************************************************************************
      21                 :            : 
      22                 :            : #include <cstdio>
      23                 :            : #include <csignal>
      24                 :            : #include <exception>
      25                 :            : #include <cfenv>
      26                 :            : 
      27                 :            : #include "NoWarning/charm.hpp"
      28                 :            : #include "NoWarning/mpi.hpp"
      29                 :            : 
      30                 :            : #include "Exception.hpp"
      31                 :            : #include "ProcessException.hpp"
      32                 :            : #include "XystBuildConfig.hpp"
      33                 :            : 
      34                 :            : namespace tk {
      35                 :            : 
      36                 :            : void
      37                 :          1 : signalHandler( int signum )
      38                 :            : // *****************************************************************************
      39                 :            : // Signal handler for multiple signals, SIGABRT, SIGSEGV, etc.
      40                 :            : //! \param[in] signum Signal number
      41                 :            : //! \see https://oroboro.com/stack-trace-on-crash
      42                 :            : //! \details Signals caught:
      43                 :            : //!  SIGABRT is generated when the program calls the abort() function, such as
      44                 :            : //!          when an assert() triggers
      45                 :            : //!  SIGSEGV is generated when the program makes an illegal memory access, such
      46                 :            : //!          as reading unaligned memory, dereferencing a null pointer, reading
      47                 :            : //!          memory out of bounds etc.
      48                 :            : //!   SIGILL is generated when the program tries to execute a malformed
      49                 :            : //!          instruction. This happens when the execution pointer starts reading
      50                 :            : //!          non-program data, or when a pointer to a function is corrupted.
      51                 :            : //!   SIGFPE is generated when executing an illegal floating point instruction,
      52                 :            : //!          most commonly division by zero or floating point overflow.
      53                 :            : // *****************************************************************************
      54                 :            : {
      55                 :            :   // associate each signal with a signal name string.
      56                 :          1 :   const char* name = nullptr;
      57 [ +  - ][ -  - ]:          1 :   switch( signum ) {
            [ -  - ][ - ]
      58                 :          1 :     case SIGABRT: name = "SIGABRT";  break;
      59                 :          0 :     case SIGFPE:  name = "SIGFPE";   break;
      60                 :          0 :     case SIGILL:  name = "SIGILL";   break;
      61                 :          0 :     case SIGINT:  name = "SIGINT";   break;
      62                 :          0 :     case SIGSEGV: name = "SIGSEGV";  break;
      63                 :          0 :     case SIGTERM: name = "SIGTERM";  break;
      64                 :            :   }
      65                 :            : 
      66                 :            :   // Echo what signal is caught
      67         [ +  - ]:          1 :   if ( name )
      68                 :          1 :     fprintf( stderr, "Caught signal %d (%s)\n", signum, name );
      69                 :            :   else
      70                 :          0 :     fprintf( stderr, "Caught signal %d\n", signum );
      71                 :            : 
      72                 :            :   // Get and display backtrace
      73 [ +  - ][ +  - ]:          1 :   tk::Exception("Signal caught").handleException();
                 [ +  - ]
      74                 :            : 
      75                 :            :   // Pass the signual number to the runtime system to use as exit code
      76                 :          1 :   CkExit( signum );
      77                 :          0 : }
      78                 :            : 
      79                 :            : int
      80                 :        283 : setSignalHandlers()
      81                 :            : // *****************************************************************************
      82                 :            : // Set signal handlers for multiple signals, SIGABRT, SIGSEGV, etc
      83                 :            : //! \return Ignore, used for calling in a constructor's initializer list
      84                 :            : // *****************************************************************************
      85                 :            : {
      86                 :            :   // override Charm++'s terminate handler
      87                 :        283 :   std::set_terminate( [](){
      88 [ +  - ][ +  - ]:          1 :     tk::Exception("Terminate was called").handleException();
                 [ +  - ]
      89                 :            :     // Tell the runtime system to exit with a nonzero exit code
      90                 :          1 :     CkExit(1);
      91                 :          0 :   } );
      92                 :            : 
      93                 :        283 :   signal( SIGABRT, tk::signalHandler );
      94                 :        283 :   signal( SIGFPE,  tk::signalHandler );
      95                 :        283 :   signal( SIGILL,  tk::signalHandler );
      96                 :        283 :   signal( SIGINT,  tk::signalHandler );
      97                 :        283 :   signal( SIGSEGV, tk::signalHandler );
      98                 :        283 :   signal( SIGTERM, tk::signalHandler );
      99                 :            : 
     100                 :        283 :   feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
     101                 :            : 
     102                 :        283 :   return 0;
     103                 :            : }
     104                 :            : 
     105                 :            : void
     106                 :          1 : processExceptionCharm()
     107                 :            : // *****************************************************************************
     108                 :            : //  Process an exception from the Charm++ runtime system
     109                 :            : //! \details See Josuttis, The C++ Standard Library - A Tutorial and Reference,
     110                 :            : //!    2nd Edition, 2012.
     111                 :            : // *****************************************************************************
     112                 :            : {
     113                 :            :   try {
     114                 :          1 :     throw;      // rethrow exception to deal with it here
     115                 :            :   }
     116                 :            :   // Catch tk::Exception
     117    [ +  - ][ - ]:          1 :   catch ( tk::Exception& qe ) {
     118         [ +  - ]:          1 :     if (!CkMyPe()) qe.handleException();
     119                 :          1 :   }
     120                 :            :   // Catch std::exception and transform it into tk::Exception without
     121                 :            :   // file:line:func information
     122                 :          0 :   catch ( std::exception& se ) {
     123 [ -  - ][ -  - ]:          0 :     tk::Exception qe( se.what() );
                 [ -  - ]
     124         [ -  - ]:          0 :     if (!CkMyPe()) qe.handleException();
     125                 :          0 :   }
     126                 :            :   // Catch uncaught exception
     127                 :          0 :   catch (...) {
     128 [ -  - ][ -  - ]:          0 :     tk::Exception qe( "Non-standard exception" );
                 [ -  - ]
     129         [ -  - ]:          0 :     if (!CkMyPe()) qe.handleException();
     130                 :          0 :   }
     131                 :            : 
     132                 :            :   // Tell the runtime system to exit with a nonzero exit code
     133                 :          1 :   CkExit(1);
     134                 :          0 : }
     135                 :            : 
     136                 :            : } // tk::

Generated by: LCOV version 1.16