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