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: /*
 92:   PetscStackView - Print the current (default) PETSc stack to an ASCII file

 94:   Not Collective

 96:   Input Parameter:
 97: . file - the file pointer, or `NULL` to use `PETSC_STDOUT`

 99:   Level: developer

101:   Notes:
102:   In debug mode PETSc maintains a stack of the current function calls that can be used to help
103:   to quickly see where a problem has occurred, for example, when a signal is received. It is
104:   recommended to use the debugger if extensive information is needed to help debug the problem.

106:   The default stack is a global variable called `petscstack`.

108: .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackPrint()`, `PetscStackSAWsGrantAccess()`, `PetscStackSAWsTakeAccess()`
109: */
110: PetscErrorCode PetscStackView(FILE *file)
111: {
112:   if (!file) file = PETSC_STDOUT;
113:   if (petscstack.currentsize < 0) {
114:     /* < 0 is absolutely a corrupted stack, but this function is usually called in an error
115:      * handler, which are not capable of recovering from errors so best we can do is print
116:      * this warning */
117:     fprintf(file, "PetscStack is definitely corrupted with stack size %d\n", petscstack.currentsize);
118:   } else if (petscstack.currentsize == 0) {
119:     if (file == PETSC_STDOUT) {
120:       PetscCall((*PetscErrorPrintf)("No error traceback is available, the problem could be in the main program. \n"));
121:     } else {
122:       fprintf(file, "No error traceback is available, the problem could be in the main program. \n");
123:     }
124:   } else {
125:     char *ptr = NULL;

127:     if (file == PETSC_STDOUT) {
128:       PetscCall((*PetscErrorPrintf)("The line numbers in the error traceback are not always exact.\n"));
129:       for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
130:         if (petscstack.file[i]) PetscCall((*PetscErrorPrintf)("#%d %s() at %s:%d\n", j, petscstack.function[i], PetscCIFilename(petscstack.file[i]), PetscCILinenumber(petscstack.line[i])));
131:         else {
132:           PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
133:           if (!ptr) PetscCall((*PetscErrorPrintf)("#%d %s()\n", j, petscstack.function[i]));
134:           else PetscCall((*PetscErrorPrintf)("#%d %s\n", j, petscstack.function[i]));
135:         }
136:       }
137:     } else {
138:       fprintf(file, "The line numbers in the error traceback are not always exact.\n");
139:       for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
140:         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]));
141:         else {
142:           PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
143:           if (!ptr) fprintf(file, "[%d] #%d %s()\n", PetscGlobalRank, j, petscstack.function[i]);
144:           else fprintf(file, "[%d] #%d %s\n", PetscGlobalRank, j, petscstack.function[i]);
145:         }
146:       }
147:     }
148:   }
149:   return PETSC_SUCCESS;
150: }

152: /*
153:   PetscStackCopy - Copy the information from one PETSc stack to another

155:   Not Collective

157:   Input Parameter:
158: . sint - the stack to be copied from

160:   Output Parameter:
161: . sout - the stack to be copied to, this stack must already exist

163:   Level: developer

165:   Note:
166:   In debug mode PETSc maintains a stack of the current function calls that can be used to help
167:   to quickly see where a problem has occurred, for example, when a signal is received. It is
168:   recommended to use the debugger if extensive information is needed to help debug the problem.

170: .seealso: `PetscAttachDebugger()`, `PetscStackView()`
171: */
172: PetscErrorCode PetscStackCopy(PetscStack *sint, PetscStack *sout)
173: {
174:   if (sint) {
175:     for (int i = 0; i < sint->currentsize; ++i) {
176:       sout->function[i]     = sint->function[i];
177:       sout->file[i]         = sint->file[i];
178:       sout->line[i]         = sint->line[i];
179:       sout->petscroutine[i] = sint->petscroutine[i];
180:     }
181:     sout->currentsize = sint->currentsize;
182:   } else {
183:     sout->currentsize = 0;
184:   }
185:   return PETSC_SUCCESS;
186: }

188: /*
189:   PetscStackPrint - Prints a given PETSc stack to an ASCII file

191:   Not Collective

193:   Input Parameters:
194: + sint - the PETSc stack to print
195: - file - the file pointer

197:   Level: developer

199:   Notes:
200:   In debug mode PETSc maintains a stack of the current function calls that can be used to help
201:   to quickly see where a problem has occurred, for example, when a signal is received. It is
202:   recommended to use the debugger if extensive information is needed to help debug the problem.

204:   The default stack is a global variable called `petscstack`.

206:   Developer Note:
207:   `PetscStackPrint()` and `PetscStackView()` should be merged into a single API.

209: .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()`
210: */
211: PetscErrorCode PetscStackPrint(PetscStack *sint, FILE *fp)
212: {
213:   if (sint) {
214:     for (int i = sint->currentsize - 2; i >= 0; --i) {
215:       if (sint->file[i]) fprintf(fp, "      [%d]  %s() at %s:%d\n", PetscGlobalRank, sint->function[i], PetscCIFilename(sint->file[i]), PetscCILinenumber(sint->line[i]));
216:       else fprintf(fp, "      [%d]  %s()\n", PetscGlobalRank, sint->function[i]);
217:     }
218:   }
219:   return PETSC_SUCCESS;
220: }
221: #endif /* PetscDefined(USE_DEBUG) */