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