Actual source code: errtrace.c

  1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for fileno() */
  2: #include <petscsys.h>
  3: #include <petsc/private/petscimpl.h>
  4: #include <petscconfiginfo.h>
  5: #if PetscDefined(HAVE_UNISTD_H)
  6:   #include <unistd.h>
  7: #endif
  8: #include "err.h"
  9: #include <petsc/private/logimpl.h>

 11: #if PetscDefined(HAVE_CUPM)
 12: #include <petsc/private/deviceimpl.h>
 13: #endif

 15: static char      arch[128], hostname[128], username[128], pname[PETSC_MAX_PATH_LEN], date[128];
 16: static PetscBool PetscErrorPrintfInitializeCalled = PETSC_FALSE;
 17: static char      version[256];

 19: /*@
 20:   PetscErrorPrintfInitialize - Cache the architecture, host name, user name, program name and date so that PETSc's error-traceback printer does not need to make system calls from inside a signal handler

 22:   Collective

 24:   Level: developer

 26:   Note:
 27:   Called from `PetscInitialize()`; users normally do not need to call this directly.

 29: .seealso: `PetscErrorPrintf`, `PetscTraceBackErrorHandler()`, `PetscPushErrorHandler()`
 30: @*/
 31: PetscErrorCode PetscErrorPrintfInitialize(void)
 32: {
 33:   PetscBool use_stdout = PETSC_FALSE, use_none = PETSC_FALSE;

 35:   PetscFunctionBegin;
 36:   PetscCall(PetscGetArchType(arch, sizeof(arch)));
 37:   PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
 38:   PetscCall(PetscGetUserName(username, sizeof(username)));
 39:   PetscCall(PetscGetProgramName(pname, sizeof(pname)));
 40:   PetscCall(PetscGetDate(date, sizeof(date)));
 41:   PetscCall(PetscGetVersion(version, sizeof(version)));

 43:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-error_output_stdout", &use_stdout, NULL));
 44:   if (use_stdout) PETSC_STDERR = PETSC_STDOUT;
 45:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-error_output_none", &use_none, NULL));
 46:   if (use_none) PetscErrorPrintf = PetscErrorPrintfNone;
 47:   PetscErrorPrintfInitializeCalled = PETSC_TRUE;
 48:   PetscFunctionReturn(PETSC_SUCCESS);
 49: }

 51: /*@
 52:   PetscErrorPrintfNone - An alternative to `PetscErrorPrintfDefault()` that prints no error messages

 54:   Not Collective; No Fortran Support

 56:   Input Parameter:
 57: . format - the usual `printf()` format string

 59:   Options Database Key:
 60: . -error_output_none - install this function; the error is still handled in the same way, only the message is suppressed

 62:   Level: developer

 64: .seealso: `PetscErrorPrintf()`, `PetscErrorPrintfDefault()`, `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscPrintf()`,
 65:           `PetscPushErrorHandler()`, `PetscVFPrintf()`, `PetscHelpPrintf()`
 66: @*/
 67: PetscErrorCode PetscErrorPrintfNone(const char format[], ...)
 68: {
 69:   return PETSC_SUCCESS;
 70: }

 72: /*@
 73:   PetscErrorPrintfDefault - The default error printing used by `PetscErrorPrintf()`

 75:   Not Collective; No Fortran Support

 77:   Input Parameter:
 78: . format - the usual `printf()` format string

 80:   Options Database Key:
 81: . -error_output_stdout - write the error messages to `stdout` instead of the default `stderr`

 83:   Level: developer

 85: .seealso: `PetscErrorPrintf()`, `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscPrintf()`, `PetscPushErrorHandler()`,
 86:           `PetscVFPrintf()`, `PetscHelpPrintf()`, `PetscErrorPrintfNone()`
 87: @*/
 88: PetscErrorCode PetscErrorPrintfDefault(const char format[], ...)
 89: {
 90:   va_list          Argp;
 91:   static PetscBool PetscErrorPrintfCalled = PETSC_FALSE;

 93:   /*
 94:       This function does not call PetscFunctionBegin and PetscFunctionReturn() because
 95:     it may be called by PetscStackView().

 97:       This function does not do error checking because it is called by the error handlers.
 98:   */

100:   if (!PetscErrorPrintfCalled) PetscErrorPrintfCalled = PETSC_TRUE;

102:   (void)PetscFPrintf(PETSC_COMM_SELF, PETSC_STDERR, "[%d]PETSC ERROR: ", PetscGlobalRank);
103:   va_start(Argp, format);
104:   (void)(*PetscVFPrintf)(PETSC_STDERR, format, Argp);
105:   va_end(Argp);
106:   return PETSC_SUCCESS;
107: }

109: /*
110:    On some systems when the stderr is nested through several levels of shell script
111:    before being passed to a file the isatty() falsely returns true resulting in
112:    the screen highlight variables being passed through the test harness. Therefore
113:    simply do not highlight when the PETSC_STDERR is PETSC_STDOUT.
114: */
115: static void PetscErrorPrintfHilight(void)
116: {
117: #if PetscDefined(HAVE_UNISTD_H) && PetscDefined(USE_ISATTY)
118:   if (PetscErrorPrintf == PetscErrorPrintfDefault && PETSC_STDERR != PETSC_STDOUT) {
119:     if (isatty(fileno(PETSC_STDERR))) fprintf(PETSC_STDERR, "\033[1;31m");
120:   }
121: #endif
122: }

124: static void PetscErrorPrintfNormal(void)
125: {
126: #if PetscDefined(HAVE_UNISTD_H) && PetscDefined(USE_ISATTY)
127:   if (PetscErrorPrintf == PetscErrorPrintfDefault && PETSC_STDERR != PETSC_STDOUT) {
128:     if (isatty(fileno(PETSC_STDERR))) fprintf(PETSC_STDERR, "\033[0;39m\033[0;49m");
129:   }
130: #endif
131: }

133: PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void);

135: static PETSC_TLS PetscBool petsc_traceback_error_silent = PETSC_FALSE;

137: /*@
138:   PetscTraceBackErrorHandler - Default error handler routine that generates a traceback on error detection.

140:   Not Collective, No Fortran Support

142:   Input Parameters:
143: + comm - communicator over which error occurred
144: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
145: . fun  - the function name
146: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
147: . mess - an error text string, usually just printed to the screen
148: . n    - the generic error number
149: . p    - `PETSC_ERROR_INITIAL` if this is the first call the error handler, otherwise `PETSC_ERROR_REPEAT`
150: - ctx  - error handler context

152:   Options Database Keys:
153: + -error_output_stdout - output the error messages to `stdout` instead of the default `stderr`
154: - -error_output_none   - do not output the error messages

156:   Notes:
157:   Users do not directly call this routine

159:   Use `PetscPushErrorHandler()` to set the desired error handler.

161:   Level: developer

163: .seealso: `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
164:           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscReturnErrorHandler()`, `PetscEmacsClientErrorHandler()`,
165:            `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`, `PetscErrorType`
166:  @*/
167: PetscErrorCode PetscTraceBackErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, PetscCtx ctx)
168: {
169:   PetscMPIInt rank = 0;

171:   (void)ctx;
172:   if (comm != PETSC_COMM_SELF) MPI_Comm_rank(comm, &rank);

174:   // reinitialize the error handler when a new initializing error is detected
175:   if (p != PETSC_ERROR_REPEAT) {
176:     petsc_traceback_error_silent = PETSC_FALSE;
177:     if (PetscCIEnabledPortableErrorOutput) {
178:       PetscMPIInt size = 1;

180:       if (comm != MPI_COMM_NULL) MPI_Comm_size(comm, &size);
181:       petscabortmpifinalize = (size == PetscGlobalSize) ? PETSC_TRUE : PETSC_FALSE;
182:     }
183:   }

185:   if (rank == 0 && (!PetscCIEnabledPortableErrorOutput || PetscGlobalRank == 0) && (p != PETSC_ERROR_REPEAT || !petsc_traceback_error_silent)) {
186:     static int cnt    = 1;
187:     PetscBool  python = (n == PETSC_ERR_PYTHON && cnt == 1) ? PETSC_TRUE : PETSC_FALSE;

189:     if (p == PETSC_ERROR_INITIAL || python) {
190:       PetscErrorPrintfHilight();
191:       (void)(*PetscErrorPrintf)("--------------------- Error Message --------------------------------------------------------------\n");
192:       PetscErrorPrintfNormal();
193:       if (cnt > 1) {
194:         (void)(*PetscErrorPrintf)("  It appears a new error in the code was triggered after a previous error, possibly because:\n");
195:         (void)(*PetscErrorPrintf)("  -  The first error was not properly handled via (for example) the use of\n");
196:         (void)(*PetscErrorPrintf)("     PetscCall(TheFunctionThatErrors()); or\n");
197:         (void)(*PetscErrorPrintf)("  -  The second error was triggered while handling the first error.\n");
198:         (void)(*PetscErrorPrintf)("  Above is the traceback for the previous unhandled error, below the traceback for the next error\n");
199:         (void)(*PetscErrorPrintf)("  ALL ERRORS in the PETSc libraries are fatal, you should add the appropriate error checking to the code\n");
200:         cnt = 1;
201:       }
202:     }
203:     if (cnt == 1) {
204:       if (n == PETSC_ERR_MEM || n == PETSC_ERR_MEM_LEAK) (void)PetscErrorMemoryMessage(n);
205:       else {
206:         const char *text;
207:         (void)PetscErrorMessage(n, &text, NULL);
208:         if (text) (void)(*PetscErrorPrintf)("%s\n", text);
209:       }
210:       if (python) (void)PetscPythonPrintError();
211:       else if (mess) (void)(*PetscErrorPrintf)("%s\n", mess);
212: #if defined(PETSC_PKG_CUDA_MIN_ARCH)
213:       int confCudaArch = PETSC_PKG_CUDA_MIN_ARCH;    // if PETSc was configured with numbered CUDA arches, get the min arch.
214:       int runCudaArch  = PetscDeviceCUPMRuntimeArch; // 0 indicates the code has never initialized a cuda device.
215:       if (runCudaArch && confCudaArch > runCudaArch) {
216:         (void)(*PetscErrorPrintf)("WARNING! Run on a CUDA device with GPU architecture %d, but PETSc was configured with a minimal GPU architecture %d.\n", runCudaArch, confCudaArch);
217:         (void)(*PetscErrorPrintf)("If it is a cudaErrorNoKernelImageForDevice error, you may need to reconfigure PETSc with --with-cuda-arch=%d or --with-cuda-arch=%d,%d\n", runCudaArch, runCudaArch, confCudaArch);
218:       }
219: #endif
220:       (void)PetscOptionsLeftError();
221:       (void)(*PetscErrorPrintf)("See https://petsc.org/release/faq/ for trouble shooting.\n");
222:       if (!PetscCIEnabledPortableErrorOutput) {
223:         size_t clen;

225:         (void)(*PetscErrorPrintf)("%s\n", version);
226:         if (PetscErrorPrintfInitializeCalled) (void)(*PetscErrorPrintf)("%s with %d MPI process(es) and PETSC_ARCH %s on %s by %s %s\n", pname, PetscGlobalSize, arch, hostname, username, date);
227:         (void)PetscStrlen(petscconfigureoptions, &clen);
228:         (void)(*PetscErrorPrintf)("Configure options: %s\n", clen ? petscconfigureoptions : "none used");
229:       }
230:     }
231:     /* print line of stack trace */
232:     if (fun) (void)(*PetscErrorPrintf)("#%d %s() at %s:%d\n", cnt++, fun, PetscCIFilename(file), PetscCILinenumber(line));
233:     else if (file) (void)(*PetscErrorPrintf)("#%d %s:%d\n", cnt++, PetscCIFilename(file), PetscCILinenumber(line));
234:     if (fun) {
235:       PetscBool ismain = PETSC_FALSE;

237:       (void)PetscStrncmp(fun, "main", 4, &ismain);
238:       if (ismain) {
239:         if (n <= PETSC_ERR_MIN_VALUE || n >= PETSC_ERR_MAX_VALUE) (void)(*PetscErrorPrintf)("Reached the main program with an out-of-range error code %d. This should never happen\n", n);
240:         (void)PetscOptionsViewError();
241:         PetscErrorPrintfHilight();
242:         (void)(*PetscErrorPrintf)("----------------End of Error Message -------send entire error message to petsc-maint@mcs.anl.gov----------\n");
243:         PetscErrorPrintfNormal();
244:       }
245:     }
246:   } else {
247:     // silence this process's stacktrace if it is not the root of an originating error
248:     if (p != PETSC_ERROR_REPEAT && rank) petsc_traceback_error_silent = PETSC_TRUE;
249:     if (fun) {
250:       PetscBool ismain = PETSC_FALSE;

252:       (void)PetscStrncmp(fun, "main", 4, &ismain);
253:       if (ismain && petsc_traceback_error_silent) {
254:         /* This results from PetscError() being called in main: PETSCABORT()
255:            will be called after the error handler.  But this thread is not the
256:            root rank of the communicator that initialized the error.  So sleep
257:            to allow the root thread to finish its printing.

259:            (Unless this is running CI, in which case do not sleep because
260:            we expect all processes to call MPI_Finalize() and make a clean
261:            exit.) */
262:         if (!PetscCIEnabledPortableErrorOutput) (void)PetscSleep(10.0);
263:       }
264:     }
265:   }
266:   return n;
267: }