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