Actual source code: pstack.c
2: #include <petsc/private/petscimpl.h>
4: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
5: PetscStack petscstack;
6: #endif
8: #if defined(PETSC_HAVE_SAWS)
9: #include <petscviewersaws.h>
11: static PetscBool amsmemstack = PETSC_FALSE;
13: /*@C
14: PetscStackSAWsGrantAccess - Grants access of the PETSc stack frames to the SAWs publisher
16: Collective on `PETSC_COMM_WORLD`?
18: Level: developer
20: Developers Note:
21: Cannot use `PetscFunctionBegin`/`PetrscFunctionReturn()` or `PetscCallSAWs()` since it may be 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: Developers Note:
41: Cannot use `PetscFunctionBegin`/`PetscFunctionReturn()` or `PetscCallSAWs()` since it may be used within those routines
43: .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()`
44: @*/
45: void PetscStackSAWsTakeAccess(void)
46: {
47: if (amsmemstack) {
48: /* ignore any errors from SAWs */
49: SAWs_Lock();
50: }
51: }
53: PetscErrorCode PetscStackViewSAWs(void)
54: {
55: PetscMPIInt rank;
57: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
58: if (rank) return PETSC_SUCCESS;
59: #if PetscDefined(USE_DEBUG)
60: PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/functions", petscstack.function, 20, SAWs_READ, SAWs_STRING));
61: PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/__current_size", &petscstack.currentsize, 1, SAWs_READ, SAWs_INT));
62: #endif
63: amsmemstack = PETSC_TRUE;
64: return PETSC_SUCCESS;
65: }
67: PetscErrorCode PetscStackSAWsViewOff(void)
68: {
69: PetscFunctionBegin;
70: if (!amsmemstack) PetscFunctionReturn(PETSC_SUCCESS);
71: PetscCallSAWs(SAWs_Delete, ("/PETSc/Stack"));
72: amsmemstack = PETSC_FALSE;
73: PetscFunctionReturn(PETSC_SUCCESS);
74: }
75: #endif /* PETSC_HAVE_SAWS */
77: #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
78: PetscErrorCode PetscStackSetCheck(PetscBool check)
79: {
80: petscstack.check = check;
81: return PETSC_SUCCESS;
82: }
84: PetscErrorCode PetscStackReset(void)
85: {
86: memset(&petscstack, 0, sizeof(petscstack));
87: return PETSC_SUCCESS;
88: }
90: /*@C
91: PetscStackView - Print the current (default) PETSc stack to an ASCII file
93: Not Collective
95: Input Parameter:
96: . file - the file pointer, or `NULL` to use `PETSC_STDOUT`
98: Level: developer
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.
105: The default stack is a global variable called `petscstack`.
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: PetscCall((*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: char *ptr = NULL;
126: if (file == PETSC_STDOUT) {
127: PetscCall((*PetscErrorPrintf)("The line numbers in the error traceback are not always exact.\n"));
128: for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
129: if (petscstack.file[i]) PetscCall((*PetscErrorPrintf)("#%d %s() at %s:%d\n", j, petscstack.function[i], PetscCIFilename(petscstack.file[i]), PetscCILinenumber(petscstack.line[i])));
130: else {
131: PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
132: if (!ptr) PetscCall((*PetscErrorPrintf)("#%d %s()\n", j, petscstack.function[i]));
133: else PetscCall((*PetscErrorPrintf)("#%d %s\n", j, petscstack.function[i]));
134: }
135: }
136: } else {
137: fprintf(file, "The line numbers in the error traceback are not always exact.\n");
138: for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
139: 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]));
140: else {
141: PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
142: if (!ptr) fprintf(file, "[%d] #%d %s()\n", PetscGlobalRank, j, petscstack.function[i]);
143: else fprintf(file, "[%d] #%d %s\n", PetscGlobalRank, j, petscstack.function[i]);
144: }
145: }
146: }
147: }
148: return PETSC_SUCCESS;
149: }
151: /*@C
152: PetscStackCopy - Copy the information from one PETSc stack to another
154: Not Collective
156: Input Parameter:
157: . sint - the stack to be copied from
159: Output Parameter:
160: . sout - the stack to be copied to, this stack must already exist
162: Level: developer
164: Note:
165: 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
166: occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
167: help debug the problem.
169: .seealso: `PetscAttachDebugger()`, `PetscStackView()`
170: @*/
171: PetscErrorCode PetscStackCopy(PetscStack *sint, PetscStack *sout)
172: {
173: if (sint) {
174: for (int i = 0; i < sint->currentsize; ++i) {
175: sout->function[i] = sint->function[i];
176: sout->file[i] = sint->file[i];
177: sout->line[i] = sint->line[i];
178: sout->petscroutine[i] = sint->petscroutine[i];
179: }
180: sout->currentsize = sint->currentsize;
181: } else {
182: sout->currentsize = 0;
183: }
184: return PETSC_SUCCESS;
185: }
187: /*@C
188: PetscStackPrint - Prints a given PETSc stack to an ASCII file
190: Not Collective
192: Input Parameters:
193: + sint - the PETSc stack to print
194: - file - the file pointer
196: Level: developer
198: Notes:
199: 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
200: occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
201: help debug the problem.
203: The default stack is a global variable called `petscstack`.
205: Developer Note:
206: `PetscStackPrint()` and `PetscStackView()` should be merged into a single API.
208: .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()`
209: @*/
210: PetscErrorCode PetscStackPrint(PetscStack *sint, FILE *fp)
211: {
212: if (sint) {
213: for (int i = sint->currentsize - 2; i >= 0; --i) {
214: if (sint->file[i]) fprintf(fp, " [%d] %s() at %s:%d\n", PetscGlobalRank, sint->function[i], PetscCIFilename(sint->file[i]), PetscCILinenumber(sint->line[i]));
215: else fprintf(fp, " [%d] %s()\n", PetscGlobalRank, sint->function[i]);
216: }
217: }
218: return PETSC_SUCCESS;
219: }
220: #endif /* PetscDefined(USE_DEBUG) */