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