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