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