1 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 2 3 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 4 PetscStack petscstack; 5 #endif 6 7 #if defined(PETSC_HAVE_SAWS) 8 #include <petscviewersaws.h> 9 10 static PetscBool amsmemstack = PETSC_FALSE; 11 12 /*@ 13 PetscStackSAWsGrantAccess - Grants access of the PETSc stack frames to the SAWs publisher 14 15 Collective on `PETSC_COMM_WORLD`? 16 17 Level: developer 18 19 Developer Notes: 20 Cannot use `PetscFunctionBegin`/`PetscFunctionReturn()` or `PetscCallSAWs()` since it may be 21 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 (void)SAWs_Unlock(); 30 } 31 } 32 33 /*@ 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 Developer Notes: 41 Cannot use `PetscFunctionBegin`/`PetscFunctionReturn()` or `PetscCallSAWs()` since it may be 42 used within those routines 43 44 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsGrantAccess()` 45 @*/ 46 void PetscStackSAWsTakeAccess(void) 47 { 48 if (amsmemstack) { 49 /* ignore any errors from SAWs */ 50 (void)SAWs_Lock(); 51 } 52 } 53 54 PetscErrorCode PetscStackViewSAWs(void) 55 { 56 PetscMPIInt rank; 57 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 } 67 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 */ 77 78 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY) 79 PetscErrorCode PetscStackSetCheck(PetscBool check) 80 { 81 petscstack.check = check; 82 return PETSC_SUCCESS; 83 } 84 85 PetscErrorCode PetscStackReset(void) 86 { 87 memset(&petscstack, 0, sizeof(petscstack)); 88 return PETSC_SUCCESS; 89 } 90 91 // PetscClangLinter pragma disable: -fdoc-sowing-chars 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_STDERR` 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 If `file` is `PETSC_STDERR` (or `NULL`) then `PetscErrorPrintf()` is used to print the stack, otherwise `fprintf()` is used. 108 109 Developer Note: 110 The default stack is a global variable called `petscstack`. 111 112 .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackPrint()`, `PetscStackSAWsGrantAccess()`, `PetscStackSAWsTakeAccess()` 113 */ 114 PetscErrorCode PetscStackView(FILE *file) 115 { 116 if (!file) file = PETSC_STDERR; 117 if (petscstack.currentsize < 0) { 118 /* < 0 is absolutely a corrupted stack, but this function is usually called in an error 119 * handler, which are not capable of recovering from errors so best we can do is print 120 * this warning */ 121 fprintf(file, "PetscStack is definitely corrupted with stack size %d\n", petscstack.currentsize); 122 } else if (petscstack.currentsize == 0) { 123 if (file == PETSC_STDERR) { 124 PetscCall((*PetscErrorPrintf)("No error traceback is available, the problem could be in the main program. \n")); 125 } else { 126 fprintf(file, "No error traceback is available, the problem could be in the main program. \n"); 127 } 128 } else { 129 char *ptr = NULL; 130 131 if (file == PETSC_STDERR) { 132 PetscCall((*PetscErrorPrintf)("The line numbers in the error traceback may not be exact.\n")); 133 for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) { 134 if (petscstack.file[i]) PetscCall((*PetscErrorPrintf)("#%d %s() at %s:%d\n", j, petscstack.function[i], PetscCIFilename(petscstack.file[i]), PetscCILinenumber(petscstack.line[i]))); 135 else { 136 PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr)); 137 if (!ptr) PetscCall((*PetscErrorPrintf)("#%d %s()\n", j, petscstack.function[i])); 138 else PetscCall((*PetscErrorPrintf)("#%d %s\n", j, petscstack.function[i])); 139 } 140 } 141 } else { 142 fprintf(file, "The line numbers in the error traceback are not always exact.\n"); 143 for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) { 144 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])); 145 else { 146 PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr)); 147 if (!ptr) fprintf(file, "[%d] #%d %s()\n", PetscGlobalRank, j, petscstack.function[i]); 148 else fprintf(file, "[%d] #%d %s\n", PetscGlobalRank, j, petscstack.function[i]); 149 } 150 } 151 } 152 } 153 return PETSC_SUCCESS; 154 } 155 156 /* 157 PetscStackCopy - Copy the information from one PETSc stack to another 158 159 Not Collective 160 161 Input Parameter: 162 . sint - the stack to be copied from 163 164 Output Parameter: 165 . sout - the stack to be copied to, this stack must already exist 166 167 Level: developer 168 169 Note: 170 In debug mode PETSc maintains a stack of the current function calls that can be used to help 171 to quickly see where a problem has occurred, for example, when a signal is received. It is 172 recommended to use the debugger if extensive information is needed to help debug the problem. 173 174 .seealso: `PetscAttachDebugger()`, `PetscStackView()` 175 */ 176 PetscErrorCode PetscStackCopy(PetscStack *sint, PetscStack *sout) 177 { 178 if (sint) { 179 for (int i = 0; i < sint->currentsize; ++i) { 180 sout->function[i] = sint->function[i]; 181 sout->file[i] = sint->file[i]; 182 sout->line[i] = sint->line[i]; 183 sout->petscroutine[i] = sint->petscroutine[i]; 184 } 185 sout->currentsize = sint->currentsize; 186 } else { 187 sout->currentsize = 0; 188 } 189 return PETSC_SUCCESS; 190 } 191 192 // PetscClangLinter pragma disable: -fdoc-sowing-chars 193 /* 194 PetscStackPrint - Prints a given PETSc stack to an ASCII file 195 196 Not Collective 197 198 Input Parameters: 199 + sint - the PETSc stack to print 200 - fp - the file pointer 201 202 Level: developer 203 204 Notes: 205 In debug mode PETSc maintains a stack of the current function calls that can be used to help 206 to quickly see where a problem has occurred, for example, when a signal is received. It is 207 recommended to use the debugger if extensive information is needed to help debug the problem. 208 209 The default stack is a global variable called `petscstack`. 210 211 Developer Note: 212 `PetscStackPrint()` and `PetscStackView()` should be merged into a single API. 213 214 .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()` 215 */ 216 PetscErrorCode PetscStackPrint(PetscStack *sint, FILE *fp) 217 { 218 if (sint) { 219 for (int i = sint->currentsize; i >= 0; --i) { 220 if (sint->file[i]) fprintf(fp, " [%d] %s() at %s:%d\n", PetscGlobalRank, sint->function[i], PetscCIFilename(sint->file[i]), PetscCILinenumber(sint->line[i])); 221 else fprintf(fp, " [%d] %s()\n", PetscGlobalRank, sint->function[i]); 222 } 223 } 224 return PETSC_SUCCESS; 225 } 226 #endif /* PetscDefined(USE_DEBUG) */ 227