Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
ErrorHandler.cpp
Go to the documentation of this file.
1 #include "moab/ErrorHandler.hpp"
2 #include "ErrorOutput.hpp"
3 #ifdef MOAB_HAVE_MPI
4 #include "moab_mpi.h"
5 #endif
6 
7 #include <cstdlib>
8 #include <cassert>
9 
10 #ifdef _WIN32
11 #include <io.h>
12 #include <windows.h>
13 namespace
14 {
15 void sleep( int sec )
16 {
17  Sleep( sec * 1000 );
18 }
19 } // namespace
20 #else
21 #include <unistd.h>
22 #endif
23 
24 namespace moab
25 {
26 
27 static ErrorOutput* errorOutput = NULL;
28 static std::string lastError = "No error";
29 
31 {
32  if( NULL == errorOutput )
33  {
34  errorOutput = new( std::nothrow ) ErrorOutput( stderr );
35  assert( NULL != errorOutput );
37  }
38 }
39 
41 {
42  if( NULL != errorOutput )
43  {
44  delete errorOutput;
45  errorOutput = NULL;
46  }
47 }
48 
50 {
51  return ( NULL != errorOutput );
52 }
53 
54 void MBErrorHandler_GetLastError( std::string& error )
55 {
56  error = lastError;
57 }
58 
59 void MBTraceBackErrorHandler( int line,
60  const char* func,
61  const char* file,
62  const char* dir,
63  const char* err_msg,
64  ErrorType err_type )
65 {
66  if( NULL == errorOutput ) return;
67 
68  // For a globally fatal error, get world rank of current processor, so that it is only printed
69  // from processor 0 For a per-processor relevant error, set rank of current processor to 0, so
70  // that it is always printed
71  int rank = 0;
72  if( MB_ERROR_TYPE_NEW_GLOBAL == err_type && errorOutput->have_rank() ) rank = errorOutput->get_rank();
73 
74  if( 0 == rank )
75  {
76  // Print the error message for a new error
77  if( MB_ERROR_TYPE_EXISTING != err_type && NULL != err_msg )
78  {
79  errorOutput->print( "--------------------- Error Message ------------------------------------\n" );
80  errorOutput->printf( "%s!\n", err_msg );
81  lastError = err_msg;
82  }
83 
84  // Print a line of stack trace for a new error, or an existing one
85  errorOutput->printf( "%s() line %d in %s%s\n", func, line, dir, file );
86  }
87  else
88  {
89  // Do not print the error message or stack trace, since processor 0 will print them
90  // Sleep 10 seconds before aborting so it will not accidently kill process 0
91  sleep( 10 );
92  abort();
93  }
94 }
95 
96 ErrorCode MBError( int line,
97  const char* func,
98  const char* file,
99  const char* dir,
100  ErrorCode err_code,
101  const char* err_msg,
102  ErrorType err_type )
103 {
104  // When this routine is called to handle an existing error (instead of creating a new one),
105  // we need to check if the returned non-success result from a function might be a non-error
106  // condition. If no last error message was ever set, just return the given error code.
107  if( MB_ERROR_TYPE_EXISTING == err_type && "No error" == lastError ) return err_code;
108 
109  MBTraceBackErrorHandler( line, func, file, dir, err_msg, err_type );
110 
111 #ifdef MOAB_HAVE_MPI
112  // If this is called from the main() routine we call MPI_Abort() to allow
113  // the parallel program to be properly shutdown
114  if( strncmp( func, "main", 4 ) == 0 ) MPI_Abort( MPI_COMM_WORLD, err_code );
115 #endif
116 
117  return err_code;
118 }
119 
120 } // namespace moab