1 2 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 3 4 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 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 Developer Notes: 21 Cannot use `PetscFunctionBegin`/`PetrscFunctionReturn()` or `PetscCallSAWs()` since it may be 22 used within those routines 23 24 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()` 25 @*/ 26 void PetscStackSAWsGrantAccess(void) 27 { 28 if (amsmemstack) { 29 /* ignore any errors from SAWs */ 30 SAWs_Unlock(); 31 } 32 } 33 34 /*@C 35 PetscStackSAWsTakeAccess - Takes access of the PETSc stack frames from the SAWs publisher 36 37 Collective on `PETSC_COMM_WORLD`? 38 39 Level: developer 40 41 Developer Notes: 42 Cannot use `PetscFunctionBegin`/`PetscFunctionReturn()` or `PetscCallSAWs()` since it may be 43 used within those routines 44 45 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsGrantAccess()` 46 @*/ 47 void PetscStackSAWsTakeAccess(void) 48 { 49 if (amsmemstack) { 50 /* ignore any errors from SAWs */ 51 SAWs_Lock(); 52 } 53 } 54 55 PetscErrorCode PetscStackViewSAWs(void) 56 { 57 PetscMPIInt rank; 58 59 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 60 if (rank) return PETSC_SUCCESS; 61 #if PetscDefined(USE_DEBUG) 62 PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/functions", petscstack.function, 20, SAWs_READ, SAWs_STRING)); 63 PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/__current_size", &petscstack.currentsize, 1, SAWs_READ, SAWs_INT)); 64 #endif 65 amsmemstack = PETSC_TRUE; 66 return PETSC_SUCCESS; 67 } 68 69 PetscErrorCode PetscStackSAWsViewOff(void) 70 { 71 PetscFunctionBegin; 72 if (!amsmemstack) PetscFunctionReturn(PETSC_SUCCESS); 73 PetscCallSAWs(SAWs_Delete, ("/PETSc/Stack")); 74 amsmemstack = PETSC_FALSE; 75 PetscFunctionReturn(PETSC_SUCCESS); 76 } 77 #endif /* PETSC_HAVE_SAWS */ 78 79 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY) 80 PetscErrorCode PetscStackSetCheck(PetscBool check) 81 { 82 petscstack.check = check; 83 return PETSC_SUCCESS; 84 } 85 86 PetscErrorCode PetscStackReset(void) 87 { 88 memset(&petscstack, 0, sizeof(petscstack)); 89 return PETSC_SUCCESS; 90 } 91 92 /* 93 PetscStackView - Print the current (default) PETSc stack to an ASCII file 94 95 Not Collective 96 97 Input Parameter: 98 . file - the file pointer, or `NULL` to use `PETSC_STDOUT` 99 100 Level: developer 101 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. 106 107 The default stack is a global variable called `petscstack`. 108 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; 127 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 } 152 153 /* 154 PetscStackCopy - Copy the information from one PETSc stack to another 155 156 Not Collective 157 158 Input Parameter: 159 . sint - the stack to be copied from 160 161 Output Parameter: 162 . sout - the stack to be copied to, this stack must already exist 163 164 Level: developer 165 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. 170 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 } 188 189 /* 190 PetscStackPrint - Prints a given PETSc stack to an ASCII file 191 192 Not Collective 193 194 Input Parameters: 195 + sint - the PETSc stack to print 196 - file - the file pointer 197 198 Level: developer 199 200 Notes: 201 In debug mode PETSc maintains a stack of the current function calls that can be used to help 202 to quickly see where a problem has occurred, for example, when a signal is received. It is 203 recommended to use the debugger if extensive information is needed to help debug the problem. 204 205 The default stack is a global variable called `petscstack`. 206 207 Developer Note: 208 `PetscStackPrint()` and `PetscStackView()` should be merged into a single API. 209 210 .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()` 211 */ 212 PetscErrorCode PetscStackPrint(PetscStack *sint, FILE *fp) 213 { 214 if (sint) { 215 for (int i = sint->currentsize - 2; i >= 0; --i) { 216 if (sint->file[i]) fprintf(fp, " [%d] %s() at %s:%d\n", PetscGlobalRank, sint->function[i], PetscCIFilename(sint->file[i]), PetscCILinenumber(sint->line[i])); 217 else fprintf(fp, " [%d] %s()\n", PetscGlobalRank, sint->function[i]); 218 } 219 } 220 return PETSC_SUCCESS; 221 } 222 #endif /* PetscDefined(USE_DEBUG) */ 223