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