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