Xyst test code coverage report
Current view: top level - Base - ProcessException.cpp (source / functions) Coverage Total Hit
Commit: 1fb74642dd9d7732b67f32dec2f2762e238d3fa7 Lines: 60.5 % 43 26
Test Date: 2025-08-13 22:46:33 Functions: 100.0 % 4 4
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 23.8 % 42 10

             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-2025 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 [ +  - ][ +  - ]:           5 :   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                 :         298 : 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                 :         299 :   std::set_terminate( [](){
      88 [ +  - ][ +  - ]:           5 :     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                 :         298 :   signal( SIGABRT, tk::signalHandler );
      94                 :         298 :   signal( SIGFPE,  tk::signalHandler );
      95                 :         298 :   signal( SIGILL,  tk::signalHandler );
      96                 :         298 :   signal( SIGINT,  tk::signalHandler );
      97                 :         298 :   signal( SIGSEGV, tk::signalHandler );
      98                 :         298 :   signal( SIGTERM, tk::signalHandler );
      99                 :             : 
     100                 :         298 :   feenableexcept( FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW );
     101                 :             : 
     102                 :         298 :   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 2.0-1