Ignore:
Timestamp:
07/23/08 11:19:39 (6 years ago)
Author:
jdsiiro
Message:

Changes to core UTILIB concurrent with the (ongoing) Acro/COLIN
AppRequest/AppResponse? rework.

  • More classes are now Any-comparable and Any-printable:
  • exception_mngr can now generate demangled stack traces (if compiled

with UTILIB_HAVE_EXECINFO and UTILIB_HAVE_CXXABI)

  • silenced numerous compiler warnings (thrown by g++ with "-W -Wall")
File:
1 edited

Legend:

Unmodified
Added
Removed
  • utilib/trunk/src/core/utilib/exception_mngr.cpp

    r1437 r1480  
    1313 
    1414#include <utilib/utilib_config.h> 
     15#include <utilib/exception_mngr.h> 
     16 
    1517#ifdef UTILIB_HAVE_MPI 
    1618#include <mpi.h> 
    1719#endif 
    18  
    19 #include <utilib/exception_mngr.h> 
    20  
     20#ifdef UTILIB_YES_COMMONIO 
     21#include <utilib/CommonIO.h> 
     22#endif 
     23#ifdef UTILIB_HAVE_EXECINFO 
     24#include <execinfo.h> 
     25#endif 
     26#ifdef UTILIB_HAVE_CXXABI 
     27#include <cxxabi.h> 
     28#endif 
     29#ifdef _MSC_VER 
     30#include <dbghelp.h> 
     31#endif 
     32 
     33using std::endl; 
     34using std::string; 
    2135 
    2236namespace utilib { 
     
    2640  { } 
    2741 
     42 
     43std::string demangledName(const char* mangled) 
     44{ 
     45#if defined(UTILIB_HAVE_CXXABI) 
     46   int stat; 
     47   char *demangled = abi::__cxa_demangle(mangled,0,0,&stat); 
     48   std::string ans = ( demangled == NULL ? mangled : demangled ); 
     49   if (demangled) 
     50      free(demangled); 
     51 
     52   return ans; 
     53#elif defined(_MSC_VER) 
     54   // I think (hope?!?) this works... 
     55   CHAR buf[1024]; 
     56   DWORD len 
     57      = UnDecorateSymbolName( mangled.c_str(), buf, sizeof(buf),  
     58                              UNDNAME_COMPLETE ); 
     59   return std::string( len == 0 ? mangled : buf ); 
     60#else 
     61   return mangled; 
     62#endif 
     63} 
     64 
     65 
    2866namespace exception_mngr { 
     67 
     68namespace { 
    2969 
    3070/// local variable to store exception mode 
    3171handle_t exception_mode = Standard; 
    3272 
     73/// local variable to store current exception pointer 
     74null_fn_type exit_function_pointer = &default_exitfn; 
     75 
     76/// local variable to store the state of the stack_trace() flag 
     77#ifdef NDEBUG 
     78bool stack_trace_flag = false; 
     79#else 
     80bool stack_trace_flag = true; 
     81#endif 
     82 
     83} // namespace (local) 
     84 
     85 
     86// actually declare the static exception message buffer 
     87std::string exception_message_buffer = string(); 
     88 
     89 
    3390handle_t mode() 
    3491  { return exception_mode; } 
     
    3794  { exception_mode = mode_; } 
    3895 
    39  
    40 /// local variable to store current exception pointer 
    41 null_fn_type exit_function_pointer = &default_exitfn; 
    4296 
    4397void exit_function() 
     
    51105  } 
    52106 
     107bool stack_trace() 
     108{ 
     109   return stack_trace_flag;  
     110} 
     111 
     112void set_stack_trace(bool stack) 
     113{ 
     114   stack_trace_flag = stack; 
     115} 
     116 
     117 
     118 
     119void generate_stack_trace(std::ostringstream &os) 
     120{ 
     121#ifdef UTILIB_HAVE_EXECINFO 
     122   void * array[25]; 
     123   int nSize = backtrace(array, 25); 
     124   char ** symbols = backtrace_symbols(array, nSize); 
     125   if ( symbols == NULL ) 
     126      return; 
     127 
     128   os << "Stack trace:" << endl; 
     129   for (int i = 0; i < nSize; i++) 
     130   { 
     131      os << "     "; 
     132      char* sym_s = strchr(symbols[i], '('); 
     133      char* sym_e = strrchr(symbols[i], ')'); 
     134      char* sym_o = ( sym_s == NULL ? NULL : strrchr(sym_s, '+') ); 
     135      if (( sym_s != NULL ) && ( sym_o > sym_s ) && ( sym_e > sym_o )) 
     136      { 
     137         os << string(symbols[i], sym_s-symbols[i]) << ": "; 
     138 
     139         // Split symbol & offset into separate C strings (overwrite the "+") 
     140         *sym_o = 0; 
     141         os << demangledName(sym_s+1) << " (+" << string(sym_o+1) << endl; 
     142      } 
     143      else 
     144         os << symbols[i] << endl; 
     145   } 
     146   free(symbols); 
     147#else 
     148   os << "[stack trace disabled: compile with UTILIB_HAVE_EXECINFO" << endl; 
     149#endif 
     150} 
     151 
     152 
     153/** Process an exception based on the exception manager mode. */ 
     154void handle_exception( const ExceptionGenerator_base &exception,  
     155                       std::ostringstream& msg ) 
     156{ 
     157std::ostringstream omsg; 
     158 
     159#ifdef UTILIB_HAVE_MPI 
     160int mpiActive=0; 
     161MPI_Initialized(&mpiActive); 
     162if (mpiActive) { 
     163   int rank; 
     164   MPI_Comm_rank(MPI_COMM_WORLD,&rank); 
     165   omsg << "(PN" << rank << ")  "; 
     166   } 
     167#endif 
     168 
     169omsg << msg.str(); 
     170 
     171if ( stack_trace() ) 
     172{ 
     173   omsg << std::endl; 
     174   generate_stack_trace(omsg); 
     175} 
     176 
     177switch ( utilib::exception_mngr::mode() ) { 
     178  case Standard: 
     179        utilib::exception_mngr::exit_function(); 
     180        // 
     181        // Note: if we simply throw omsg.str().c_str(), then 
     182        // that may create a temporary char* that is deleted after the 
     183        // throw occurs.  This can lead to the situation where the 
     184        // catch block for this exception processes a deleted array. 
     185        // 
     186        exception_message_buffer = omsg.str(); 
     187        exception.throw_it( exception_message_buffer ); 
     188 
     189  case Abort: 
     190        #ifdef UTILIB_HAVE_MPI 
     191        /* 
     192        if (mpiActive) 
     193           MPI_Abort(MPI_COMM_WORLD,1); 
     194        */ 
     195        #endif 
     196        utilib::exception_mngr::exit_function(); 
     197        #ifdef UTILIB_YES_COMMONIO 
     198        ucerr << omsg.str().c_str() << std::endl; 
     199        CommonIO::end_all(); 
     200        #else 
     201        std::cerr << omsg.str().c_str() << std::endl; 
     202        #endif 
     203        abort(); 
     204        break; 
     205 
     206  case Exit: 
     207        #ifdef UTILIB_HAVE_MPI 
     208        if (mpiActive) 
     209           MPI_Abort(MPI_COMM_WORLD,1); 
     210        #endif 
     211        utilib::exception_mngr::exit_function(); 
     212        #ifdef UTILIB_YES_COMMONIO 
     213        ucerr << omsg.str().c_str() << std::endl; 
     214        CommonIO::end_all(); 
     215        #else 
     216        std::cerr << omsg.str().c_str() << std::endl; 
     217        #endif 
     218        exit(-1); 
     219  } 
     220} 
     221 
    53222 
    54223} // exception_mngr namespace 
Note: See TracChangeset for help on using the changeset viewer.