xref: /petsc/src/sys/error/errtrace.c (revision 66af8762ec03dbef0e079729eb2a1734a35ed7ff)
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 (indicated by __LINE__)
156 . fun  - the function name
157 . file - the file in which the error was detected (indicated by __FILE__)
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  @*/
177 PetscErrorCode PetscTraceBackErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx)
178 {
179   PetscErrorCode ierr;
180   PetscMPIInt    rank = 0;
181 
182   (void)ctx;
183   if (comm != PETSC_COMM_SELF) MPI_Comm_rank(comm, &rank);
184 
185   // reinitialize the error handler when a new initializing error is detected
186   if (p != PETSC_ERROR_REPEAT) {
187     petsc_traceback_error_silent = PETSC_FALSE;
188     if (PetscCIEnabledPortableErrorOutput) {
189       PetscMPIInt size = 1;
190 
191       if (comm != MPI_COMM_NULL) MPI_Comm_size(comm, &size);
192       petscabortmpifinalize = (size == PetscGlobalSize) ? PETSC_TRUE : PETSC_FALSE;
193     }
194   }
195 
196   if (rank == 0 && (!PetscCIEnabledPortableErrorOutput || PetscGlobalRank == 0) && (p != PETSC_ERROR_REPEAT || !petsc_traceback_error_silent)) {
197     static int cnt = 1;
198 
199     if (p == PETSC_ERROR_INITIAL) {
200       PetscErrorPrintfHilight();
201       ierr = (*PetscErrorPrintf)("--------------------- Error Message --------------------------------------------------------------\n");
202       PetscErrorPrintfNormal();
203       if (cnt > 1) {
204         ierr = (*PetscErrorPrintf)("  It appears a new error in the code was triggered after a previous error, possibly because:\n");
205         ierr = (*PetscErrorPrintf)("  -  The first error was not properly handled via (for example) the use of\n");
206         ierr = (*PetscErrorPrintf)("     PetscCall(TheFunctionThatErrors()); or\n");
207         ierr = (*PetscErrorPrintf)("  -  The second error was triggered while handling the first error.\n");
208         ierr = (*PetscErrorPrintf)("  Above is the traceback for the previous unhandled error, below the traceback for the next error\n");
209         ierr = (*PetscErrorPrintf)("  ALL ERRORS in the PETSc libraries are fatal, you should add the appropriate error checking to the code\n");
210         cnt  = 1;
211       }
212     }
213     if (cnt == 1) {
214       if (n == PETSC_ERR_MEM || n == PETSC_ERR_MEM_LEAK) ierr = PetscErrorMemoryMessage(n);
215       else {
216         const char *text;
217         ierr = PetscErrorMessage(n, &text, NULL);
218         if (text) ierr = (*PetscErrorPrintf)("%s\n", text);
219       }
220       if (mess) ierr = (*PetscErrorPrintf)("%s\n", mess);
221       ierr = PetscOptionsLeftError();
222       ierr = (*PetscErrorPrintf)("See https://petsc.org/release/faq/ for trouble shooting.\n");
223       if (!PetscCIEnabledPortableErrorOutput) {
224         ierr = (*PetscErrorPrintf)("%s\n", version);
225         if (PetscErrorPrintfInitializeCalled) ierr = (*PetscErrorPrintf)("%s on a %s named %s by %s %s\n", pname, arch, hostname, username, date);
226         ierr = (*PetscErrorPrintf)("Configure options %s\n", petscconfigureoptions);
227       }
228     }
229     /* print line of stack trace */
230     if (fun) ierr = (*PetscErrorPrintf)("#%d %s() at %s:%d\n", cnt++, fun, PetscCIFilename(file), PetscCILinenumber(line));
231     else if (file) ierr = (*PetscErrorPrintf)("#%d %s:%d\n", cnt++, PetscCIFilename(file), PetscCILinenumber(line));
232     if (fun) {
233       PetscBool ismain = PETSC_FALSE;
234 
235       ierr = PetscStrncmp(fun, "main", 4, &ismain);
236       if (ismain) {
237         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);
238         ierr = PetscOptionsViewError();
239         PetscErrorPrintfHilight();
240         ierr = (*PetscErrorPrintf)("----------------End of Error Message -------send entire error message to petsc-maint@mcs.anl.gov----------\n");
241         PetscErrorPrintfNormal();
242       }
243     }
244   } else {
245     // silence this process's stacktrace if it is not the root of an originating error
246     if (p != PETSC_ERROR_REPEAT && rank) petsc_traceback_error_silent = PETSC_TRUE;
247     if (fun) {
248       PetscBool ismain = PETSC_FALSE;
249 
250       ierr = PetscStrncmp(fun, "main", 4, &ismain);
251       if (ismain && petsc_traceback_error_silent) {
252         /* This results from PetscError() being called in main: PETSCABORT()
253            will be called after the error handler.  But this thread is not the
254            root rank of the communicator that initialized the error.  So sleep
255            to allow the root thread to finish its printing.
256 
257            (Unless this is running CI, in which case do not sleep because
258            we expect all processes to call MPI_Finalize() and make a clean
259            exit.) */
260         if (!PetscCIEnabledPortableErrorOutput) ierr = PetscSleep(10.0);
261       }
262     }
263   }
264   (void)ierr;
265   return n;
266 }
267