Actual source code: pstack.c


  2: #include <petsc/private/petscimpl.h>

  4: #if PetscDefined(USE_DEBUG)
  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:

 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:

 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:   MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
 58:   if (rank) return 0;
 59:   #if PetscDefined(USE_DEBUG)
 60:   SAWs_Register, ("/PETSc/Stack/functions", petscstack.function, 20, SAWs_READ, SAWs_STRING);
 61:   SAWs_Register, ("/PETSc/Stack/__current_size", &petscstack.currentsize, 1, SAWs_READ, SAWs_INT);
 62:   #endif
 63:   amsmemstack = PETSC_TRUE;
 64:   return 0;
 65: }

 67: PetscErrorCode PetscStackSAWsViewOff(void)
 68: {
 69:   if (!amsmemstack) return 0;
 70:   SAWs_Delete, ("/PETSc/Stack");
 71:   amsmemstack = PETSC_FALSE;
 72:   return 0;
 73: }
 74: #endif /* PETSC_HAVE_SAWS */

 76: #if PetscDefined(USE_DEBUG)
 77: PetscErrorCode PetscStackSetCheck(PetscBool check)
 78: {
 79:   petscstack.check = check;
 80:   return 0;
 81: }

 83: PetscErrorCode PetscStackReset(void)
 84: {
 85:   memset(&petscstack, 0, sizeof(petscstack));
 86:   return 0;
 87: }

 89: /*@C
 90:    PetscStackView - Print the current (default) PETSc stack to an ASCII file

 92:    Not Collective

 94:    Input Parameter:
 95: .   file - the file pointer, or `NULL` to use `PETSC_STDOUT`

 97:    Level: developer

 99:    Notes:
100:    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
101:    occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
102:    help debug the problem.

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

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

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

150: /*@C
151:    PetscStackCopy - Copy the information from one PETSc stack to another

153:    Not Collective

155:    Input Parameter:
156: .   sint - the stack to be copied from

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

161:    Level: developer

163:    Note:
164:    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
165:    occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
166:    help debug the problem.

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

186: /*@C
187:    PetscStackPrint - Prints a given PETSc stack to an ASCII file

189:    Not Collective

191:    Input Parameters:
192: +   sint - the PETSc stack to print
193: -  file - the file pointer

195:    Level: developer

197:    Notes:
198:    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
199:    occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to
200:    help debug the problem.

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

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

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