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: Cannot use PetscFunctionBegin/Return() or PetscCallSAWs() since it may be used within those routines 21 22 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()` 23 24 @*/ 25 void PetscStackSAWsGrantAccess(void) { 26 if (amsmemstack) { 27 /* ignore any errors from SAWs */ 28 SAWs_Unlock(); 29 } 30 } 31 32 /*@C 33 PetscStackSAWsTakeAccess - Takes access of the PETSc stack frames from the SAWs publisher 34 35 Collective on PETSC_COMM_WORLD? 36 37 Level: developer 38 39 Developers Note: Cannot use PetscFunctionBegin/Return() or PetscCallSAWs() since it may be used within those routines 40 41 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()` 42 43 @*/ 44 void PetscStackSAWsTakeAccess(void) { 45 if (amsmemstack) { 46 /* ignore any errors from SAWs */ 47 SAWs_Lock(); 48 } 49 } 50 51 PetscErrorCode PetscStackViewSAWs(void) { 52 PetscMPIInt rank; 53 54 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 55 if (rank) return 0; 56 #if PetscDefined(USE_DEBUG) 57 PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/functions", petscstack.function, 20, SAWs_READ, SAWs_STRING)); 58 PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/__current_size", &petscstack.currentsize, 1, SAWs_READ, SAWs_INT)); 59 #endif 60 amsmemstack = PETSC_TRUE; 61 return 0; 62 } 63 64 PetscErrorCode PetscStackSAWsViewOff(void) { 65 PetscFunctionBegin; 66 if (!amsmemstack) PetscFunctionReturn(0); 67 PetscCallSAWs(SAWs_Delete, ("/PETSc/Stack")); 68 amsmemstack = PETSC_FALSE; 69 PetscFunctionReturn(0); 70 } 71 #endif /* PETSC_HAVE_SAWS */ 72 73 #if PetscDefined(USE_DEBUG) 74 PetscErrorCode PetscStackSetCheck(PetscBool check) { 75 petscstack.check = check; 76 return 0; 77 } 78 79 PetscErrorCode PetscStackReset(void) { 80 memset(&petscstack, 0, sizeof(petscstack)); 81 return 0; 82 } 83 84 /*@C 85 PetscStackView - Print the current (default) PETSc stack to an ASCII file 86 87 Not Collective 88 89 Input Parameter: 90 . file - the file pointer, or `NULL` to use `PETSC_STDOUT` 91 92 Level: developer 93 94 Notes: 95 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 96 occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to 97 help debug the problem. 98 99 The default stack is a global variable called `petscstack`. 100 101 .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackPrint()`, `PetscStackSAWsGrantAccess()`, `PetscStackSAWsTakeAccess()` 102 @*/ 103 PetscErrorCode PetscStackView(FILE *file) { 104 if (!file) file = PETSC_STDOUT; 105 if (petscstack.currentsize < 0) { 106 /* < 0 is absolutely a corrupted stack, but this function is usually called in an error 107 * handler, which are not capable of recovering from errors so best we can do is print 108 * this warning */ 109 fprintf(file, "PetscStack is definitely corrupted with stack size %d\n", petscstack.currentsize); 110 } else if (petscstack.currentsize == 0) { 111 if (file == PETSC_STDOUT) { 112 (*PetscErrorPrintf)("No error traceback is available, the problem could be in the main program. \n"); 113 } else { 114 fprintf(file, "No error traceback is available, the problem could be in the main program. \n"); 115 } 116 } else { 117 char *ptr; 118 119 if (file == PETSC_STDOUT) { 120 (*PetscErrorPrintf)("The line numbers in the error traceback are not always exact.\n"); 121 for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) { 122 if (petscstack.file[i]) (*PetscErrorPrintf)("#%d %s() at %s:%d\n", j, petscstack.function[i], PetscCIFilename(petscstack.file[i]), PetscCILinenumber(petscstack.line[i])); 123 else { 124 PetscStrstr(petscstack.function[i], " ", &ptr); 125 if (!ptr) (*PetscErrorPrintf)("#%d %s()\n", j, petscstack.function[i]); 126 else (*PetscErrorPrintf)("#%d %s\n", j, petscstack.function[i]); 127 } 128 } 129 } else { 130 fprintf(file, "The line numbers in the error traceback are not always exact.\n"); 131 for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) { 132 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])); 133 else { 134 PetscStrstr(petscstack.function[i], " ", &ptr); 135 if (!ptr) fprintf(file, "[%d] #%d %s()\n", PetscGlobalRank, j, petscstack.function[i]); 136 else fprintf(file, "[%d] #%d %s\n", PetscGlobalRank, j, petscstack.function[i]); 137 } 138 } 139 } 140 } 141 return 0; 142 } 143 144 /*@C 145 PetscStackCopy - Copy the information from one PETSc stack to another 146 147 Not Collective 148 149 Input Parameter: 150 . sint - the stack to be copied from 151 152 Output Parameter: 153 . sout - the stack to be copied to, this stack must already exist 154 155 Level: developer 156 157 Notes: 158 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 159 occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to 160 help debug the problem. 161 162 .seealso: `PetscAttachDebugger()`, `PetscStackView()` 163 @*/ 164 PetscErrorCode PetscStackCopy(PetscStack *sint, PetscStack *sout) { 165 if (sint) { 166 for (int i = 0; i < sint->currentsize; ++i) { 167 sout->function[i] = sint->function[i]; 168 sout->file[i] = sint->file[i]; 169 sout->line[i] = sint->line[i]; 170 sout->petscroutine[i] = sint->petscroutine[i]; 171 } 172 sout->currentsize = sint->currentsize; 173 } else { 174 sout->currentsize = 0; 175 } 176 return 0; 177 } 178 179 /*@C 180 PetscStackPrint - Prints a given PETSc stack to an ASCII file 181 182 Not Collective 183 184 Input Parameters: 185 + sint - the PETSc stack to print 186 - file - the file pointer 187 188 Level: developer 189 190 Notes: 191 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 192 occurred, for example, when a signal is received. It is recommended to use the debugger if extensive information is needed to 193 help debug the problem. 194 195 The default stack is a global variable called `petscstack`. 196 197 Developer Note: 198 `PetscStackPrint()` and `PetscStackView()` should be merged into a single API. 199 200 .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()` 201 @*/ 202 PetscErrorCode PetscStackPrint(PetscStack *sint, FILE *fp) { 203 if (sint) { 204 for (int i = sint->currentsize - 2; i >= 0; --i) { 205 if (sint->file[i]) fprintf(fp, " [%d] %s() at %s:%d\n", PetscGlobalRank, sint->function[i], PetscCIFilename(sint->file[i]), PetscCILinenumber(sint->line[i])); 206 else fprintf(fp, " [%d] %s()\n", PetscGlobalRank, sint->function[i]); 207 } 208 } 209 return 0; 210 } 211 #endif /* PetscDefined(USE_DEBUG) */ 212