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) */