1 #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for fileno() */ 2 #include <petscsys.h> /*I "petscsys.h" I*/ 3 #include <petsc/private/petscimpl.h> 4 #include <petscconfiginfo.h> 5 #if defined(PETSC_HAVE_UNISTD_H) 6 #include <unistd.h> 7 #endif 8 #include "err.h" 9 #include <petsc/private/logimpl.h> // PETSC_TLS 10 11 /*@C 12 PetscIgnoreErrorHandler - Deprecated, use `PetscReturnErrorHandler()`. Ignores the error, allows program to continue as if error did not occur 13 14 Not Collective 15 16 Input Parameters: 17 + comm - communicator over which error occurred 18 . line - the line number of the error (indicated by __LINE__) 19 . fun - the function name 20 . file - the file in which the error was detected (indicated by __FILE__) 21 . mess - an error text string, usually just printed to the screen 22 . n - the generic error number 23 . p - specific error number 24 - ctx - error handler context 25 26 Level: developer 27 28 Note: 29 Users do not directly call this routine 30 31 .seealso: `PetscReturnErrorHandler()` 32 @*/ 33 PetscErrorCode PetscIgnoreErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx) 34 { 35 (void)comm; 36 (void)line; 37 (void)fun; 38 (void)file; 39 (void)p; 40 (void)mess; 41 (void)ctx; 42 return n; 43 } 44 45 /* ---------------------------------------------------------------------------------------*/ 46 47 static char arch[128], hostname[128], username[128], pname[PETSC_MAX_PATH_LEN], date[128]; 48 static PetscBool PetscErrorPrintfInitializeCalled = PETSC_FALSE; 49 static char version[256]; 50 51 /* 52 Initializes arch, hostname, username, date so that system calls do NOT need 53 to be made during the error handler. 54 */ 55 PetscErrorCode PetscErrorPrintfInitialize(void) 56 { 57 PetscBool use_stdout = PETSC_FALSE, use_none = PETSC_FALSE; 58 59 PetscFunctionBegin; 60 PetscCall(PetscGetArchType(arch, sizeof(arch))); 61 PetscCall(PetscGetHostName(hostname, sizeof(hostname))); 62 PetscCall(PetscGetUserName(username, sizeof(username))); 63 PetscCall(PetscGetProgramName(pname, sizeof(pname))); 64 PetscCall(PetscGetDate(date, sizeof(date))); 65 PetscCall(PetscGetVersion(version, sizeof(version))); 66 67 PetscCall(PetscOptionsGetBool(NULL, NULL, "-error_output_stdout", &use_stdout, NULL)); 68 if (use_stdout) PETSC_STDERR = PETSC_STDOUT; 69 PetscCall(PetscOptionsGetBool(NULL, NULL, "-error_output_none", &use_none, NULL)); 70 if (use_none) PetscErrorPrintf = PetscErrorPrintfNone; 71 PetscErrorPrintfInitializeCalled = PETSC_TRUE; 72 PetscFunctionReturn(PETSC_SUCCESS); 73 } 74 75 PetscErrorCode PetscErrorPrintfNone(const char format[], ...) 76 { 77 return PETSC_SUCCESS; 78 } 79 80 PetscErrorCode PetscErrorPrintfDefault(const char format[], ...) 81 { 82 va_list Argp; 83 static PetscBool PetscErrorPrintfCalled = PETSC_FALSE; 84 PetscErrorCode ierr; 85 86 /* 87 This function does not call PetscFunctionBegin and PetscFunctionReturn() because 88 it may be called by PetscStackView(). 89 90 This function does not do error checking because it is called by the error handlers. 91 */ 92 93 if (!PetscErrorPrintfCalled) { 94 PetscErrorPrintfCalled = PETSC_TRUE; 95 96 /* 97 On the SGI machines and Cray T3E, if errors are generated "simultaneously" by 98 different processors, the messages are printed all jumbled up; to try to 99 prevent this we have each processor wait based on their rank 100 */ 101 #if defined(PETSC_CAN_SLEEP_AFTER_ERROR) 102 { 103 PetscMPIInt rank = PetscGlobalRank > 8 ? 8 : PetscGlobalRank; 104 ierr = PetscSleep((PetscReal)rank); 105 (void)ierr; 106 } 107 #endif 108 } 109 110 ierr = PetscFPrintf(PETSC_COMM_SELF, PETSC_STDERR, "[%d]PETSC ERROR: ", PetscGlobalRank); 111 va_start(Argp, format); 112 ierr = (*PetscVFPrintf)(PETSC_STDERR, format, Argp); 113 (void)ierr; 114 va_end(Argp); 115 return PETSC_SUCCESS; 116 } 117 118 /* 119 On some systems when the stderr is nested through several levels of shell script 120 before being passed to a file the isatty() falsely returns true resulting in 121 the screen highlight variables being passed through the test harness. Therefore 122 simply do not highlight when the PETSC_STDERR is PETSC_STDOUT. 123 */ 124 static void PetscErrorPrintfHilight(void) 125 { 126 #if defined(PETSC_HAVE_UNISTD_H) && defined(PETSC_USE_ISATTY) 127 if (PetscErrorPrintf == PetscErrorPrintfDefault && PETSC_STDERR != PETSC_STDOUT) { 128 if (isatty(fileno(PETSC_STDERR))) fprintf(PETSC_STDERR, "\033[1;31m"); 129 } 130 #endif 131 } 132 133 static void PetscErrorPrintfNormal(void) 134 { 135 #if defined(PETSC_HAVE_UNISTD_H) && defined(PETSC_USE_ISATTY) 136 if (PetscErrorPrintf == PetscErrorPrintfDefault && PETSC_STDERR != PETSC_STDOUT) { 137 if (isatty(fileno(PETSC_STDERR))) fprintf(PETSC_STDERR, "\033[0;39m\033[0;49m"); 138 } 139 #endif 140 } 141 142 PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void); 143 144 static PETSC_TLS PetscBool petsc_traceback_error_silent = PETSC_FALSE; 145 146 /*@C 147 148 PetscTraceBackErrorHandler - Default error handler routine that generates 149 a traceback on error detection. 150 151 Not Collective 152 153 Input Parameters: 154 + comm - communicator over which error occurred 155 . line - the line number of the error (usually indicated by `__LINE__` in the calling routine) 156 . fun - the function name 157 . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine) 158 . mess - an error text string, usually just printed to the screen 159 . n - the generic error number 160 . p - `PETSC_ERROR_INITIAL` if this is the first call the error handler, otherwise `PETSC_ERROR_REPEAT` 161 - ctx - error handler context 162 163 Options Database Keys: 164 + -error_output_stdout - output the error messages to `stdout` instead of the default `stderr` 165 - -error_output_none - do not output the error messages 166 167 Notes: 168 Users do not directly call this routine 169 170 Use `PetscPushErrorHandler()` to set the desired error handler. 171 172 Level: developer 173 174 .seealso: `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, 175 `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscReturnErrorHandler()`, `PetscEmacsClientErrorHandler()`, 176 `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`, `PetscErrorType` 177 @*/ 178 PetscErrorCode PetscTraceBackErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx) 179 { 180 PetscErrorCode ierr; 181 PetscMPIInt rank = 0; 182 183 (void)ctx; 184 if (comm != PETSC_COMM_SELF) MPI_Comm_rank(comm, &rank); 185 186 // reinitialize the error handler when a new initializing error is detected 187 if (p != PETSC_ERROR_REPEAT) { 188 petsc_traceback_error_silent = PETSC_FALSE; 189 if (PetscCIEnabledPortableErrorOutput) { 190 PetscMPIInt size = 1; 191 192 if (comm != MPI_COMM_NULL) MPI_Comm_size(comm, &size); 193 petscabortmpifinalize = (size == PetscGlobalSize) ? PETSC_TRUE : PETSC_FALSE; 194 } 195 } 196 197 if (rank == 0 && (!PetscCIEnabledPortableErrorOutput || PetscGlobalRank == 0) && (p != PETSC_ERROR_REPEAT || !petsc_traceback_error_silent)) { 198 static int cnt = 1; 199 200 if (p == PETSC_ERROR_INITIAL) { 201 PetscErrorPrintfHilight(); 202 ierr = (*PetscErrorPrintf)("--------------------- Error Message --------------------------------------------------------------\n"); 203 PetscErrorPrintfNormal(); 204 if (cnt > 1) { 205 ierr = (*PetscErrorPrintf)(" It appears a new error in the code was triggered after a previous error, possibly because:\n"); 206 ierr = (*PetscErrorPrintf)(" - The first error was not properly handled via (for example) the use of\n"); 207 ierr = (*PetscErrorPrintf)(" PetscCall(TheFunctionThatErrors()); or\n"); 208 ierr = (*PetscErrorPrintf)(" - The second error was triggered while handling the first error.\n"); 209 ierr = (*PetscErrorPrintf)(" Above is the traceback for the previous unhandled error, below the traceback for the next error\n"); 210 ierr = (*PetscErrorPrintf)(" ALL ERRORS in the PETSc libraries are fatal, you should add the appropriate error checking to the code\n"); 211 cnt = 1; 212 } 213 } 214 if (cnt == 1) { 215 if (n == PETSC_ERR_MEM || n == PETSC_ERR_MEM_LEAK) ierr = PetscErrorMemoryMessage(n); 216 else { 217 const char *text; 218 ierr = PetscErrorMessage(n, &text, NULL); 219 if (text) ierr = (*PetscErrorPrintf)("%s\n", text); 220 } 221 if (mess) ierr = (*PetscErrorPrintf)("%s\n", mess); 222 ierr = PetscOptionsLeftError(); 223 ierr = (*PetscErrorPrintf)("See https://petsc.org/release/faq/ for trouble shooting.\n"); 224 if (!PetscCIEnabledPortableErrorOutput) { 225 ierr = (*PetscErrorPrintf)("%s\n", version); 226 if (PetscErrorPrintfInitializeCalled) ierr = (*PetscErrorPrintf)("%s on a %s named %s by %s %s\n", pname, arch, hostname, username, date); 227 ierr = (*PetscErrorPrintf)("Configure options %s\n", petscconfigureoptions); 228 } 229 } 230 /* print line of stack trace */ 231 if (fun) ierr = (*PetscErrorPrintf)("#%d %s() at %s:%d\n", cnt++, fun, PetscCIFilename(file), PetscCILinenumber(line)); 232 else if (file) ierr = (*PetscErrorPrintf)("#%d %s:%d\n", cnt++, PetscCIFilename(file), PetscCILinenumber(line)); 233 if (fun) { 234 PetscBool ismain = PETSC_FALSE; 235 236 ierr = PetscStrncmp(fun, "main", 4, &ismain); 237 if (ismain) { 238 if ((n <= PETSC_ERR_MIN_VALUE) || (n >= PETSC_ERR_MAX_VALUE)) ierr = (*PetscErrorPrintf)("Reached the main program with an out-of-range error code %d. This should never happen\n", n); 239 ierr = PetscOptionsViewError(); 240 PetscErrorPrintfHilight(); 241 ierr = (*PetscErrorPrintf)("----------------End of Error Message -------send entire error message to petsc-maint@mcs.anl.gov----------\n"); 242 PetscErrorPrintfNormal(); 243 } 244 } 245 } else { 246 // silence this process's stacktrace if it is not the root of an originating error 247 if (p != PETSC_ERROR_REPEAT && rank) petsc_traceback_error_silent = PETSC_TRUE; 248 if (fun) { 249 PetscBool ismain = PETSC_FALSE; 250 251 ierr = PetscStrncmp(fun, "main", 4, &ismain); 252 if (ismain && petsc_traceback_error_silent) { 253 /* This results from PetscError() being called in main: PETSCABORT() 254 will be called after the error handler. But this thread is not the 255 root rank of the communicator that initialized the error. So sleep 256 to allow the root thread to finish its printing. 257 258 (Unless this is running CI, in which case do not sleep because 259 we expect all processes to call MPI_Finalize() and make a clean 260 exit.) */ 261 if (!PetscCIEnabledPortableErrorOutput) ierr = PetscSleep(10.0); 262 } 263 } 264 } 265 (void)ierr; 266 return n; 267 } 268