xref: /petsc/src/sys/error/errtrace.c (revision 47dad92f5893b4bb94b8967582c4fe440fbcb11c)
1 
2 #include "petscsys.h"        /*I "petscsys.h" I*/
3 #include "petscconfiginfo.h"
4 
5 #undef __FUNCT__
6 #define __FUNCT__ "PetscIgnoreErrorHandler"
7 /*@C
8    PetscIgnoreErrorHandler - Ignores the error, allows program to continue as if error did not occure
9 
10    Not Collective
11 
12    Input Parameters:
13 +  comm - communicator over which error occurred
14 .  line - the line number of the error (indicated by __LINE__)
15 .  func - the function where error is detected (indicated by __FUNCT__)
16 .  file - the file in which the error was detected (indicated by __FILE__)
17 .  dir - the directory of the file (indicated by __SDIR__)
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    Notes for experienced users:
32    Use PetscPushErrorHandler() to set the desired error handler.  The
33    currently available PETSc error handlers include PetscTraceBackErrorHandler(),
34    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscMPIAbortErrorHandler()
35 
36    Concepts: error handler^traceback
37    Concepts: traceback^generating
38 
39 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
40           PetscAbortErrorHandler(), PetscTraceBackErrorHandler()
41  @*/
42 PetscErrorCode  PetscIgnoreErrorHandler(MPI_Comm comm,int line,const char *fun,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx)
43 {
44   PetscFunctionBegin;
45   PetscFunctionReturn(n);
46 }
47 
48 /* ---------------------------------------------------------------------------------------*/
49 
50 static char  arch[10],hostname[64],username[16],pname[PETSC_MAX_PATH_LEN],date[64];
51 static PetscBool  PetscErrorPrintfInitializeCalled = PETSC_FALSE;
52 static char version[256];
53 
54 #undef __FUNCT__
55 #define __FUNCT__ "PetscErrorPrintfInitialize"
56 /*
57    Initializes arch, hostname, username,date so that system calls do NOT need
58    to be made during the error handler.
59 */
60 PetscErrorCode  PetscErrorPrintfInitialize()
61 {
62   PetscErrorCode ierr;
63   PetscBool      use_stdout = PETSC_FALSE,use_none = PETSC_FALSE;
64 
65   PetscFunctionBegin;
66   ierr = PetscGetArchType(arch,10);CHKERRQ(ierr);
67   ierr = PetscGetHostName(hostname,64);CHKERRQ(ierr);
68   ierr = PetscGetUserName(username,16);CHKERRQ(ierr);
69   ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
70   ierr = PetscGetDate(date,64);CHKERRQ(ierr);
71   ierr = PetscGetVersion(version,256);CHKERRQ(ierr);
72 
73   ierr = PetscOptionsGetBool(PETSC_NULL,"-error_output_stdout",&use_stdout,PETSC_NULL);CHKERRQ(ierr);
74   if (use_stdout) {
75     PETSC_STDERR = PETSC_STDOUT;
76   }
77   ierr = PetscOptionsGetBool(PETSC_NULL,"-error_output_none",&use_none,PETSC_NULL);CHKERRQ(ierr);
78   if (use_none) {
79     PetscErrorPrintf = PetscErrorPrintfNone;
80   }
81   PetscErrorPrintfInitializeCalled = PETSC_TRUE;
82   PetscFunctionReturn(0);
83 }
84 
85 #undef __FUNCT__
86 #define __FUNCT__ "PetscErrorPrintfNone"
87 PetscErrorCode  PetscErrorPrintfNone(const char format[],...)
88 {
89   return 0;
90 }
91 
92 #undef __FUNCT__
93 #define __FUNCT__ "PetscErrorPrintfDefault"
94 PetscErrorCode  PetscErrorPrintfDefault(const char format[],...)
95 {
96   va_list           Argp;
97   static PetscBool  PetscErrorPrintfCalled = PETSC_FALSE;
98 
99   /*
100       This function does not call PetscFunctionBegin and PetscFunctionReturn() because
101     it may be called by PetscStackView().
102 
103       This function does not do error checking because it is called by the error handlers.
104   */
105 
106   if (!PetscErrorPrintfCalled) {
107     PetscErrorPrintfCalled = PETSC_TRUE;
108 
109     /*
110         On the SGI machines and Cray T3E, if errors are generated  "simultaneously" by
111       different processors, the messages are printed all jumbled up; to try to
112       prevent this we have each processor wait based on their rank
113     */
114 #if defined(PETSC_CAN_SLEEP_AFTER_ERROR)
115     {
116       PetscMPIInt rank;
117       if (PetscGlobalRank > 8) rank = 8; else rank = PetscGlobalRank;
118       PetscSleep((PetscReal)rank);
119     }
120 #endif
121   }
122 
123   PetscFPrintf(PETSC_COMM_SELF,PETSC_STDERR,"[%d]PETSC ERROR: ",PetscGlobalRank);
124   va_start(Argp,format);
125   (*PetscVFPrintf)(PETSC_STDERR,format,Argp);
126   va_end(Argp);
127   return 0;
128 }
129 
130 #undef __FUNCT__
131 #define __FUNCT__ "PetscTraceBackErrorHandler"
132 /*@C
133 
134    PetscTraceBackErrorHandler - Default error handler routine that generates
135    a traceback on error detection.
136 
137    Not Collective
138 
139    Input Parameters:
140 +  comm - communicator over which error occurred
141 .  line - the line number of the error (indicated by __LINE__)
142 .  func - the function where error is detected (indicated by __FUNCT__)
143 .  file - the file in which the error was detected (indicated by __FILE__)
144 .  dir - the directory of the file (indicated by __SDIR__)
145 .  mess - an error text string, usually just printed to the screen
146 .  n - the generic error number
147 .  p - PETSC_ERROR_INITIAL if this is the first call the the error handler, otherwise PETSC_ERROR_REPEAT
148 -  ctx - error handler context
149 
150    Level: developer
151 
152    Notes:
153    Most users need not directly employ this routine and the other error
154    handlers, but can instead use the simplified interface SETERRQ, which has
155    the calling sequence
156 $     SETERRQ(comm,number,n,mess)
157 
158    Notes for experienced users:
159    Use PetscPushErrorHandler() to set the desired error handler.  The
160    currently available PETSc error handlers include PetscTraceBackErrorHandler(),
161    PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler(), and PetscMPIAbortErrorHandler()
162 
163    Concepts: error handler^traceback
164    Concepts: traceback^generating
165 
166 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(),
167           PetscAbortErrorHandler()
168  @*/
169 PetscErrorCode  PetscTraceBackErrorHandler(MPI_Comm comm,int line,const char *fun,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p,const char *mess,void *ctx)
170 {
171   PetscLogDouble    mem,rss;
172   PetscBool         flg1 = PETSC_FALSE,flg2 = PETSC_FALSE;
173   PetscMPIInt       rank = 0;
174 
175   PetscFunctionBegin;
176   if (comm != PETSC_COMM_SELF) {
177     MPI_Comm_rank(comm,&rank);
178   }
179   if (!rank) {
180     if (p == PETSC_ERROR_INITIAL) {
181       (*PetscErrorPrintf)("--------------------- Error Message ------------------------------------\n");
182       if (n == PETSC_ERR_MEM) {
183 	(*PetscErrorPrintf)("Out of memory. This could be due to allocating\n");
184 	(*PetscErrorPrintf)("too large an object or bleeding by not properly\n");
185 	(*PetscErrorPrintf)("destroying unneeded objects.\n");
186 	PetscMallocGetCurrentUsage(&mem);
187 	PetscMemoryGetCurrentUsage(&rss);
188 	PetscOptionsGetBool(PETSC_NULL,"-malloc_dump",&flg1,PETSC_NULL);
189 	PetscOptionsGetBool(PETSC_NULL,"-malloc_log",&flg2,PETSC_NULL);
190 	if (flg2) {
191 	  PetscMallocDumpLog(stdout);
192 	} else {
193 	  (*PetscErrorPrintf)("Memory allocated %D Memory used by process %D\n",(PetscInt)mem,(PetscInt)rss);
194 	  if (flg1) {
195 	    PetscMallocDump(stdout);
196 	  } else {
197 	    (*PetscErrorPrintf)("Try running with -malloc_dump or -malloc_log for info.\n");
198 	  }
199 	}
200       } else {
201         const char *text;
202         PetscErrorMessage(n,&text,PETSC_NULL);
203         if (text) (*PetscErrorPrintf)("%s!\n",text);
204       }
205       if (mess) {
206 	(*PetscErrorPrintf)("%s!\n",mess);
207       }
208       (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
209       (*PetscErrorPrintf)("%s\n",version);
210       (*PetscErrorPrintf)("See docs/changes/index.html for recent updates.\n");
211       (*PetscErrorPrintf)("See docs/faq.html for hints about trouble shooting.\n");
212       (*PetscErrorPrintf)("See docs/index.html for manual pages.\n");
213       (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
214       if (PetscErrorPrintfInitializeCalled) {
215 	(*PetscErrorPrintf)("%s on a %s named %s by %s %s\n",pname,arch,hostname,username,date);
216       }
217       (*PetscErrorPrintf)("Libraries linked from %s\n",PETSC_LIB_DIR);
218       (*PetscErrorPrintf)("Configure run at %s\n",petscconfigureruntime);
219       (*PetscErrorPrintf)("Configure options %s\n",petscconfigureoptions);
220       (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
221     }
222     /* print line of stack trace */
223     (*PetscErrorPrintf)("%s() line %d in %s%s\n",fun,line,dir,file);
224   } else {
225     /* do not print error messages since process 0 will print them, sleep before aborting so will not accidently kill process 0*/
226     PetscSleep(10.0);
227     abort();
228   }
229   PetscFunctionReturn(n);
230 }
231 
232 #if defined(PETSC_CLANGUAGE_CXX) && !defined(PETSC_USE_EXTERN_CXX)
233 #undef __FUNCT__
234 #define __FUNCT__ "PetscTraceBackErrorHandlerCxx"
235 /*@C
236 
237    PetscTraceBackErrorHandlerCxx - Error handler routine that generate a traceback in a C++ stream.
238 
239    Not Collective
240 
241    Input Parameters:
242 +  comm - communicator over which error occurred
243 .  line - the line number of the error (indicated by __LINE__)
244 .  func - the function where error is detected (indicated by __FUNCT__)
245 .  file - the file in which the error was detected (indicated by __FILE__)
246 .  dir - the directory of the file (indicated by __SDIR__)
247 .  n - the generic error number
248 .  p - PETSC_ERROR_INITIAL or PETSC_ERROR_REPEAT
249 .  mess - the error message
250 +  ctx - error handling context, in this case the C++ stream.
251 
252    Level: developer
253 
254    Notes:
255    Most users need not directly employ this routine and the other error
256    handlers, but can instead use the simplified interface SETERROR, which has
257    the calling sequence
258 $     SETERROR(number,n,mess)
259 
260    Concepts: error handler^traceback
261    Concepts: traceback^generating
262 
263 .seealso:  PetscPushErrorHandler(), PetscAttachDebuggerErrorHandler(), PetscAbortErrorHandler()
264  @*/
265 PetscErrorCode  PetscTraceBackErrorHandlerCxx(MPI_Comm comm,int line,const char *fun,const char* file,const char *dir,PetscErrorCode n,PetscErrorType p, const char *mess,void *ctx)
266 {
267   std::ostringstream *msg = (std::ostringstream*) ctx;
268 
269   if (p == PETSC_ERROR_INITIAL) {
270     PetscLogDouble mem, rss;
271     PetscBool      flg1 = PETSC_FALSE, flg2 = PETSC_FALSE;
272 
273     (*msg) << "--------------------- Error Message ------------------------------------" << std::endl;
274     if (n == PETSC_ERR_MEM) {
275       (*msg) << "Out of memory. This could be due to allocating" << std::endl;
276       (*msg) << "too large an object or bleeding by not properly" << std::endl;
277       (*msg) << "destroying unneeded objects." << std::endl;
278       PetscMallocGetCurrentUsage(&mem);
279       PetscMemoryGetCurrentUsage(&rss);
280       PetscOptionsGetBool(PETSC_NULL,"-malloc_dump",&flg1,PETSC_NULL);
281       PetscOptionsGetBool(PETSC_NULL,"-malloc_log",&flg2,PETSC_NULL);
282       if (flg2) {
283         //PetscMallocDumpLog(stdout);
284         (*msg) << "Option -malloc_log does not work in C++." << std::endl;
285       } else {
286         (*msg) << "Memory allocated " << mem << " Memory used by process " << rss << std::endl;
287         if (flg1) {
288           //PetscMallocDump(stdout);
289           (*msg) << "Option -malloc_dump does not work in C++." << std::endl;
290         } else {
291           (*msg) << "Try running with -malloc_dump or -malloc_log for info." << std::endl;
292         }
293       }
294     } else {
295       const char *text;
296 
297       PetscErrorMessage(n,&text,PETSC_NULL);
298       if (text) {(*msg) << text << "!" << std::endl;}
299     }
300     if (mess) {(*msg) << mess << "!" << std::endl;}
301     (*msg) << "------------------------------------------------------------------------" << std::endl;
302     (*msg) << version << std::endl;
303     (*msg) << "See docs/changes/index.html for recent updates." << std::endl;
304     (*msg) << "See docs/faq.html for hints about trouble shooting." << std::endl;
305     (*msg) << "See docs/index.html for manual pages." << std::endl;
306     (*msg) << "------------------------------------------------------------------------" << std::endl;
307     if (PetscErrorPrintfInitializeCalled) {
308       (*msg) << pname << " on a " << arch << " named " << hostname << " by " << username << " " << date << std::endl;
309     }
310     (*msg) << "Libraries linked from " << PETSC_LIB_DIR << std::endl;
311     (*msg) << "Configure run at " << petscconfigureruntime << std::endl;
312     (*msg) << "Configure options " << petscconfigureoptions << std::endl;
313     (*msg) << "------------------------------------------------------------------------" << std::endl;
314   }
315   (*msg) << fun<<"() line " << line << " in " << dir << file << std::endl;
316   return 0;
317 }
318 #endif
319