MOAB: Mesh Oriented datABase  (version 5.2.1)
ErrorHandler.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines