1 2 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 3 4 #if PetscDefined(USE_DEBUG) 5 PetscStack petscstack; 6 #endif 7 8 #if defined(PETSC_HAVE_SAWS) 9 #include <petscviewersaws.h> 10 11 static PetscBool amsmemstack = PETSC_FALSE; 12 13 /*@C 14 PetscStackSAWsGrantAccess - Grants access of the PETSc stack frames to the SAWs publisher 15 16 Collective on `PETSC_COMM_WORLD`? 17 18 Level: developer 19 20 Developers Note: 21 Cannot use `PetscFunctionBegin`/`PetrscFunctionReturn()` or `PetscCallSAWs()` since it may be used within those routines 22 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 } 32 33 /*@C 34 PetscStackSAWsTakeAccess - Takes access of the PETSc stack frames from the SAWs publisher 35 36 Collective on `PETSC_COMM_WORLD`? 37 38 Level: developer 39 40 Developers Note: 41 Cannot use `PetscFunctionBegin`/`PetscFunctionReturn()` or `PetscCallSAWs()` since it may be used within those routines 42 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 } 52 53 PetscErrorCode PetscStackViewSAWs(void) 54 { 55 PetscMPIInt rank; 56 57 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 58 if (rank) return 0; 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 0; 65 } 66 67 PetscErrorCode PetscStackSAWsViewOff(void) 68 { 69 PetscFunctionBegin; 70 if (!amsmemstack) PetscFunctionReturn(0); 71 PetscCallSAWs(SAWs_Delete, ("/PETSc/Stack")); 72 amsmemstack = PETSC_FALSE; 73 PetscFunctionReturn(0); 74 } 75 #endif /* PETSC_HAVE_SAWS */ 76 77 #if PetscDefined(USE_DEBUG) 78 PetscErrorCode PetscStackSetCheck(PetscBool check) 79 { 80 petscstack.check = check; 81 return 0; 82 } 83 84 PetscErrorCode PetscStackReset(void) 85 { 86 memset(&petscstack, 0, sizeof(petscstack)); 87 return 0; 88 } 89 90 /*@C 91 PetscStackView - Print the current (default) PETSc stack to an ASCII file 92 93 Not Collective 94 95 Input Parameter: 96 . file - the file pointer, or `NULL` to use `PETSC_STDOUT` 97 98 Level: developer 99 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. 104 105 The default stack is a global variable called `petscstack`. 106 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 (*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; 125 126 if (file == PETSC_STDOUT) { 127 (*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]) (*PetscErrorPrintf)("#%d %s() at %s:%d\n", j, petscstack.function[i], PetscCIFilename(petscstack.file[i]), PetscCILinenumber(petscstack.line[i])); 130 else { 131 PetscStrstr(petscstack.function[i], " ", &ptr); 132 if (!ptr) (*PetscErrorPrintf)("#%d %s()\n", j, petscstack.function[i]); 133 else (*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 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 0; 149 } 150 151 /*@C 152 PetscStackCopy - Copy the information from one PETSc stack to another 153 154 Not Collective 155 156 Input Parameter: 157 . sint - the stack to be copied from 158 159 Output Parameter: 160 . sout - the stack to be copied to, this stack must already exist 161 162 Level: developer 163 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. 168 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 0; 185 } 186 187 /*@C 188 PetscStackPrint - Prints a given PETSc stack to an ASCII file 189 190 Not Collective 191 192 Input Parameters: 193 + sint - the PETSc stack to print 194 - file - the file pointer 195 196 Level: developer 197 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. 202 203 The default stack is a global variable called `petscstack`. 204 205 Developer Note: 206 `PetscStackPrint()` and `PetscStackView()` should be merged into a single API. 207 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 0; 219 } 220 #endif /* PetscDefined(USE_DEBUG) */ 221