xref: /petsc/src/sys/error/pstack.c (revision 586f9135a435d5a6381b69bc5827c0012b4bcf1e)
1 
2 #include <petsc/private/petscimpl.h>        /*I  "petscsys.h"   I*/
3 
4 #if PetscDefined(USE_DEBUG)
5 PetscStack petscstack;
6 #endif
7 
8 #if defined(PETSC_HAVE_SAWS)
9 #include <petscviewersaws.h>
10 
11 static PetscBool amsmemstack = PETSC_FALSE;
12 
13 /*@C
14    PetscStackSAWsGrantAccess - Grants access of the PETSc stack frames to the SAWs publisher
15 
16    Collective on PETSC_COMM_WORLD?
17 
18    Level: developer
19 
20    Developers Note: Cannot use PetscFunctionBegin/Return() or PetscStackCallSAWs() since it may be used within those routines
21 
22 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()`
23 
24 @*/
25 void  PetscStackSAWsGrantAccess(void)
26 {
27   if (amsmemstack) {
28     /* ignore any errors from SAWs */
29     SAWs_Unlock();
30   }
31 }
32 
33 /*@C
34    PetscStackSAWsTakeAccess - Takes access of the PETSc stack frames from the SAWs publisher
35 
36    Collective on PETSC_COMM_WORLD?
37 
38    Level: developer
39 
40    Developers Note: Cannot use PetscFunctionBegin/Return() or PetscStackCallSAWs() since it may be used within those routines
41 
42 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()`
43 
44 @*/
45 void  PetscStackSAWsTakeAccess(void)
46 {
47   if (amsmemstack) {
48     /* ignore any errors from SAWs */
49     SAWs_Lock();
50   }
51 }
52 
53 PetscErrorCode PetscStackViewSAWs(void)
54 {
55   PetscMPIInt    rank;
56 
57   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
58   if (rank) return 0;
59 #if PetscDefined(USE_DEBUG)
60   PetscStackCallSAWs(SAWs_Register,("/PETSc/Stack/functions",petscstack.function,20,SAWs_READ,SAWs_STRING));
61   PetscStackCallSAWs(SAWs_Register,("/PETSc/Stack/__current_size",&petscstack.currentsize,1,SAWs_READ,SAWs_INT));
62 #endif
63   amsmemstack = PETSC_TRUE;
64   return 0;
65 }
66 
67 PetscErrorCode PetscStackSAWsViewOff(void)
68 {
69   PetscFunctionBegin;
70   if (!amsmemstack) PetscFunctionReturn(0);
71   PetscStackCallSAWs(SAWs_Delete,("/PETSc/Stack"));
72   amsmemstack = PETSC_FALSE;
73   PetscFunctionReturn(0);
74 }
75 #endif /* PETSC_HAVE_SAWS */
76 
77 #if PetscDefined(USE_DEBUG)
78 PetscErrorCode PetscStackSetCheck(PetscBool check)
79 {
80   petscstack.check = check;
81   return 0;
82 }
83 
84 PetscErrorCode PetscStackReset(void)
85 {
86   memset(&petscstack,0,sizeof(petscstack));
87   return 0;
88 }
89 
90 /*@C
91    PetscStackView - Print the current (default) PETSc stack to an ASCII file
92 
93    Not Collective
94 
95    Input Parameter:
96 .   file - the file pointer, or `NULL` to use `PETSC_STDOUT`
97 
98    Level: developer
99 
100    Notes:
101    In debug mode PETSc maintains a stack of the current function calls that can be used to help to quickly see where a problem has
102    occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
103    help debug the problem.
104 
105    The default stack is a global variable called `petscstack`.
106 
107 .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackPrint()`, `PetscStackSAWsGrantAccess()`, `PetscStackSAWsTakeAccess()`
108 @*/
109 PetscErrorCode  PetscStackView(FILE *file)
110 {
111   if (!file) file = PETSC_STDOUT;
112   if (petscstack.currentsize < 0) {
113     /* < 0 is absolutely a corrupted stack, but this function is usually called in an error
114      * handler, which are not capable of recovering from errors so best we can do is print
115      * this warning */
116     fprintf(file,"PetscStack is definitely corrupted with stack size %d\n",petscstack.currentsize);
117   } else if (petscstack.currentsize == 0) {
118     if (file == PETSC_STDOUT) {
119       (*PetscErrorPrintf)("No error traceback is available, the problem could be in the main program. \n");
120     } else {
121       fprintf(file,"No error traceback is available, the problem could be in the main program. \n");
122     }
123   } else {
124     if (file == PETSC_STDOUT) {
125       (*PetscErrorPrintf)("The EXACT line numbers in the error traceback are not available.\n");
126       (*PetscErrorPrintf)("instead the line number of the start of the function is given.\n");
127       for (int i = petscstack.currentsize-1, j = 1; i >= 0; --i, ++j) {
128         (*PetscErrorPrintf)("#%d %s() at %s:%d\n",j,petscstack.function[i],petscstack.file[i],petscstack.line[i]);
129       }
130     } else {
131       fprintf(file,"The EXACT line numbers in the error traceback are not available.\n");
132       fprintf(file,"Instead the line number of the start of the function is given.\n");
133       for (int i = petscstack.currentsize-1, j = 1; i >= 0; --i, ++j) {
134         fprintf(file,"[%d] #%d %s() at %s:%d\n",PetscGlobalRank,j,petscstack.function[i],petscstack.file[i],petscstack.line[i]);
135       }
136     }
137   }
138   return 0;
139 }
140 
141 /*@C
142    PetscStackCopy - Copy the information from one PETSc stack to another
143 
144    Not Collective
145 
146    Input Parameter:
147 .   sint - the stack to be copied from
148 
149    Output Parameter:
150 .   sout - the stack to be copied to, this stack must already exist
151 
152    Level: developer
153 
154    Notes:
155    In debug mode PETSc maintains a stack of the current function calls that can be used to help to quickly see where a problem has
156    occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
157    help debug the problem.
158 
159 .seealso: `PetscAttachDebugger()`, `PetscStackView()`
160 @*/
161 PetscErrorCode  PetscStackCopy(PetscStack *sint,PetscStack *sout)
162 {
163   if (sint) {
164     for (int i = 0; i < sint->currentsize; ++i) {
165       sout->function[i]     = sint->function[i];
166       sout->file[i]         = sint->file[i];
167       sout->line[i]         = sint->line[i];
168       sout->petscroutine[i] = sint->petscroutine[i];
169     }
170     sout->currentsize = sint->currentsize;
171   } else {
172     sout->currentsize = 0;
173   }
174   return 0;
175 }
176 
177 /*@C
178    PetscStackPrint - Prints a given PETSc stack to an ASCII file
179 
180    Not Collective
181 
182    Input Parameters:
183 +   sint - the PETSc stack to print
184 -  file - the file pointer
185 
186    Level: developer
187 
188    Notes:
189    In debug mode PETSc maintains a stack of the current function calls that can be used to help to quickly see where a problem has
190    occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
191    help debug the problem.
192 
193    The default stack is a global variable called `petscstack`.
194 
195    Developer Note:
196    `PetscStackPrint()` and `PetscStackView()` should be merged into a single API.
197 
198 .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()`
199 @*/
200 PetscErrorCode  PetscStackPrint(PetscStack *sint,FILE *fp)
201 {
202   if (sint) {
203     for (int i = sint->currentsize-2; i >= 0; --i) {
204       fprintf(fp,"      [%d]  %s() at %s:%d\n",PetscGlobalRank,sint->function[i],sint->file[i],sint->line[i]);
205     }
206   }
207   return 0;
208 }
209 #endif /* PetscDefined(USE_DEBUG) */
210