MOAB: Mesh Oriented datABase
(version 5.2.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 <stdlib.h> 00008 #include <assert.h> 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, const char* func, const char* file, const char* dir, const char* err_msg, 00060 ErrorType err_type ) 00061 { 00062 if( NULL == errorOutput ) return; 00063 00064 // For a globally fatal error, get world rank of current processor, so that it is only printed 00065 // from processor 0 For a per-processor relevant error, set rank of current processor to 0, so 00066 // that it is always printed 00067 int rank = 0; 00068 if( MB_ERROR_TYPE_NEW_GLOBAL == err_type && errorOutput->have_rank() ) rank = errorOutput->get_rank(); 00069 00070 if( 0 == rank ) 00071 { 00072 // Print the error message for a new error 00073 if( MB_ERROR_TYPE_EXISTING != err_type && NULL != err_msg ) 00074 { 00075 errorOutput->print( "--------------------- Error Message ------------------------------------\n" ); 00076 errorOutput->printf( "%s!\n", err_msg ); 00077 lastError = err_msg; 00078 } 00079 00080 // Print a line of stack trace for a new error, or an existing one 00081 errorOutput->printf( "%s() line %d in %s%s\n", func, line, dir, file ); 00082 } 00083 else 00084 { 00085 // Do not print the error message or stack trace, since processor 0 will print them 00086 // Sleep 10 seconds before aborting so it will not accidently kill process 0 00087 sleep( 10 ); 00088 abort(); 00089 } 00090 } 00091 00092 ErrorCode MBError( int line, const char* func, const char* file, const char* dir, ErrorCode err_code, 00093 const char* err_msg, ErrorType err_type ) 00094 { 00095 // When this routine is called to handle an existing error (instead of creating a new one), 00096 // we need to check if the returned non-success result from a function might be a non-error 00097 // condition. If no last error message was ever set, just return the given error code. 00098 if( MB_ERROR_TYPE_EXISTING == err_type && "No error" == lastError ) return err_code; 00099 00100 MBTraceBackErrorHandler( line, func, file, dir, err_msg, err_type ); 00101 00102 #ifdef MOAB_HAVE_MPI 00103 // If this is called from the main() routine we call MPI_Abort() to allow 00104 // the parallel program to be properly shutdown 00105 if( strncmp( func, "main", 4 ) == 0 ) MPI_Abort( MPI_COMM_WORLD, err_code ); 00106 #endif 00107 00108 return err_code; 00109 } 00110 00111 } // namespace moab