xref: /petsc/src/sys/error/errtrace.c (revision 04c3f3b8f563eff258c1de90d4e02d41e6027585)
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 
186     if (p == PETSC_ERROR_INITIAL) {
187       PetscErrorPrintfHilight();
188       ierr = (*PetscErrorPrintf)("--------------------- Error Message --------------------------------------------------------------\n");
189       PetscErrorPrintfNormal();
190       if (cnt > 1) {
191         ierr = (*PetscErrorPrintf)("  It appears a new error in the code was triggered after a previous error was not properly handled\n");
192         ierr = (*PetscErrorPrintf)("  via (for example) the use of PetscCall(TheFunctionThatErrors());\n");
193         ierr = (*PetscErrorPrintf)("  ALL ERRORS in the PETSc libraries are fatal, you should add the appropriate error checking to the code\n");
194         cnt  = 1;
195       }
196     }
197     if (cnt == 1) {
198       if (n == PETSC_ERR_MEM) {
199         ierr = (*PetscErrorPrintf)("Out of memory. This could be due to allocating\n");
200         ierr = (*PetscErrorPrintf)("too large an object or bleeding by not properly\n");
201         ierr = (*PetscErrorPrintf)("destroying unneeded objects.\n");
202         ierr = PetscMallocGetCurrentUsage(&mem);
203         ierr = PetscMemoryGetCurrentUsage(&rss);
204         ierr = PetscOptionsGetBool(NULL, NULL, "-malloc_dump", &flg1, NULL);
205         ierr = PetscOptionsGetBool(NULL, NULL, "-malloc_view", &flg2, NULL);
206         ierr = PetscOptionsHasName(NULL, NULL, "-malloc_view_threshold", &flg3);
207         if (flg2 || flg3) ierr = PetscMallocView(stdout);
208         else {
209           ierr = (*PetscErrorPrintf)("Memory allocated %.0f Memory used by process %.0f\n", mem, rss);
210           if (flg1) ierr = PetscMallocDump(stdout);
211           else ierr = (*PetscErrorPrintf)("Try running with -malloc_dump or -malloc_view for info.\n");
212         }
213       } else {
214         const char *text;
215         ierr = PetscErrorMessage(n, &text, NULL);
216         if (text) ierr = (*PetscErrorPrintf)("%s\n", text);
217       }
218       if (mess) ierr = (*PetscErrorPrintf)("%s\n", mess);
219       ierr = PetscOptionsLeftError();
220       ierr = (*PetscErrorPrintf)("See https://petsc.org/release/faq/ for trouble shooting.\n");
221       if (!PetscCIEnabledPortableErrorOutput) {
222         ierr = (*PetscErrorPrintf)("%s\n", version);
223         if (PetscErrorPrintfInitializeCalled) ierr = (*PetscErrorPrintf)("%s on a %s named %s by %s %s\n", pname, arch, hostname, username, date);
224         ierr = (*PetscErrorPrintf)("Configure options %s\n", petscconfigureoptions);
225       }
226     }
227     /* print line of stack trace */
228     if (fun) ierr = (*PetscErrorPrintf)("#%d %s() at %s:%d\n", cnt++, fun, PetscCIFilename(file), PetscCILinenumber(line));
229     else if (file) ierr = (*PetscErrorPrintf)("#%d %s:%d\n", cnt++, PetscCIFilename(file), PetscCILinenumber(line));
230     if (fun) {
231       PetscBool ismain = PETSC_FALSE;
232 
233       ierr = PetscStrncmp(fun, "main", 4, &ismain);
234       if (ismain) {
235         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);
236         ierr = PetscOptionsViewError();
237         PetscErrorPrintfHilight();
238         ierr = (*PetscErrorPrintf)("----------------End of Error Message -------send entire error message to petsc-maint@mcs.anl.gov----------\n");
239         PetscErrorPrintfNormal();
240       }
241     }
242   } else {
243     /* do not print error messages since process 0 will print them, sleep before aborting so will not accidentally kill process 0*/
244     ierr = PetscSleep(10.0);
245     exit(0);
246   }
247   (void)ierr;
248   return n;
249 }
250