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