MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include "moab/ErrorHandler.hpp" 00002 #include "ErrorOutput.hpp" 00003 #ifdef MOAB_HAVE_MPI 00004 #include "moab_mpi.h" 00005 #endif 00006 00007 #include <cstdlib> 00008 #include <cassert> 00009 00010 #ifdef _WIN32 00011 #include <io.h> 00012 #include <windows.h> 00013 namespace 00014 { 00015 void sleep( int sec ) 00016 { 00017 Sleep( sec * 1000 ); 00018 } 00019 } // namespace 00020 #else 00021 #include <unistd.h> 00022 #endif 00023 00024 namespace moab 00025 { 00026 00027 static ErrorOutput* errorOutput = NULL; 00028 static std::string lastError = "No error"; 00029 00030 void MBErrorHandler_Init() 00031 { 00032 if( NULL == errorOutput ) 00033 { 00034 errorOutput = new( std::nothrow ) ErrorOutput( stderr ); 00035 assert( NULL != errorOutput ); 00036 errorOutput->use_world_rank(); 00037 } 00038 } 00039 00040 void MBErrorHandler_Finalize() 00041 { 00042 if( NULL != errorOutput ) 00043 { 00044 delete errorOutput; 00045 errorOutput = NULL; 00046 } 00047 } 00048 00049 bool MBErrorHandler_Initialized() 00050 { 00051 return ( NULL != errorOutput ); 00052 } 00053 00054 void MBErrorHandler_GetLastError( std::string& error ) 00055 { 00056 error = lastError; 00057 } 00058 00059 void MBTraceBackErrorHandler( int line, 00060 const char* func, 00061 const char* file, 00062 const char* dir, 00063 const char* err_msg, 00064 ErrorType err_type ) 00065 { 00066 if( NULL == errorOutput ) return; 00067 00068 // For a globally fatal error, get world rank of current processor, so that it is only printed 00069 // from processor 0 For a per-processor relevant error, set rank of current processor to 0, so 00070 // that it is always printed 00071 int rank = 0; 00072 if( MB_ERROR_TYPE_NEW_GLOBAL == err_type && errorOutput->have_rank() ) rank = errorOutput->get_rank(); 00073 00074 if( 0 == rank ) 00075 { 00076 // Print the error message for a new error 00077 if( MB_ERROR_TYPE_EXISTING != err_type && NULL != err_msg ) 00078 { 00079 errorOutput->print( "--------------------- Error Message ------------------------------------\n" ); 00080 errorOutput->printf( "%s!\n", err_msg ); 00081 lastError = err_msg; 00082 } 00083 00084 // Print a line of stack trace for a new error, or an existing one 00085 errorOutput->printf( "%s() line %d in %s%s\n", func, line, dir, file ); 00086 } 00087 else 00088 { 00089 // Do not print the error message or stack trace, since processor 0 will print them 00090 // Sleep 10 seconds before aborting so it will not accidently kill process 0 00091 sleep( 10 ); 00092 abort(); 00093 } 00094 } 00095 00096 ErrorCode MBError( int line, 00097 const char* func, 00098 const char* file, 00099 const char* dir, 00100 ErrorCode err_code, 00101 const char* err_msg, 00102 ErrorType err_type ) 00103 { 00104 // When this routine is called to handle an existing error (instead of creating a new one), 00105 // we need to check if the returned non-success result from a function might be a non-error 00106 // condition. If no last error message was ever set, just return the given error code. 00107 if( MB_ERROR_TYPE_EXISTING == err_type && "No error" == lastError ) return err_code; 00108 00109 MBTraceBackErrorHandler( line, func, file, dir, err_msg, err_type ); 00110 00111 #ifdef MOAB_HAVE_MPI 00112 // If this is called from the main() routine we call MPI_Abort() to allow 00113 // the parallel program to be properly shutdown 00114 if( strncmp( func, "main", 4 ) == 0 ) MPI_Abort( MPI_COMM_WORLD, err_code ); 00115 #endif 00116 00117 return err_code; 00118 } 00119 00120 } // namespace moab