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