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