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