xref: /petsc/src/sys/error/pstack.c (revision 2507309694b01f78fec25ddd35683bc574a688a9)
127104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I  "petscsys.h"   I*/
2d9262e54SJed Brown 
3dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
427104ee2SJacob Faibussowitsch PetscStack petscstack;
527104ee2SJacob Faibussowitsch #endif
615681b3cSBarry Smith 
7e04113cfSBarry Smith #if defined(PETSC_HAVE_SAWS)
8e04113cfSBarry Smith   #include <petscviewersaws.h>
915681b3cSBarry Smith 
102657e9d9SBarry Smith static PetscBool amsmemstack = PETSC_FALSE;
1115681b3cSBarry Smith 
1215681b3cSBarry Smith /*@C
13e04113cfSBarry Smith   PetscStackSAWsGrantAccess - Grants access of the PETSc stack frames to the SAWs publisher
1415681b3cSBarry Smith 
15811af0c4SBarry Smith   Collective on `PETSC_COMM_WORLD`?
1615681b3cSBarry Smith 
1715681b3cSBarry Smith   Level: developer
1815681b3cSBarry Smith 
1910450e9eSJacob Faibussowitsch   Developer Notes:
2010450e9eSJacob Faibussowitsch   Cannot use `PetscFunctionBegin`/`PetrscFunctionReturn()` or `PetscCallSAWs()` since it may be
2110450e9eSJacob Faibussowitsch   used within those routines
2215681b3cSBarry Smith 
23db781477SPatrick Sanan .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()`
2415681b3cSBarry Smith @*/
25d71ae5a4SJacob Faibussowitsch void PetscStackSAWsGrantAccess(void)
26d71ae5a4SJacob Faibussowitsch {
27ec957eceSBarry Smith   if (amsmemstack) {
2816ad0300SBarry Smith     /* ignore any errors from SAWs */
299a492a5cSBarry Smith     SAWs_Unlock();
3015681b3cSBarry Smith   }
31d9262e54SJed Brown }
32d9262e54SJed Brown 
3315681b3cSBarry Smith /*@C
34586f9135SBarry Smith   PetscStackSAWsTakeAccess - Takes access of the PETSc stack frames from the SAWs publisher
3515681b3cSBarry Smith 
36811af0c4SBarry Smith   Collective on `PETSC_COMM_WORLD`?
3715681b3cSBarry Smith 
3815681b3cSBarry Smith   Level: developer
3915681b3cSBarry Smith 
4010450e9eSJacob Faibussowitsch   Developer Notes:
4110450e9eSJacob Faibussowitsch   Cannot use `PetscFunctionBegin`/`PetscFunctionReturn()` or `PetscCallSAWs()` since it may be
4210450e9eSJacob Faibussowitsch   used within those routines
4315681b3cSBarry Smith 
4410450e9eSJacob Faibussowitsch .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsGrantAccess()`
4515681b3cSBarry Smith @*/
46d71ae5a4SJacob Faibussowitsch void PetscStackSAWsTakeAccess(void)
47d71ae5a4SJacob Faibussowitsch {
48ec957eceSBarry Smith   if (amsmemstack) {
4916ad0300SBarry Smith     /* ignore any errors from SAWs */
509a492a5cSBarry Smith     SAWs_Lock();
5115681b3cSBarry Smith   }
5215681b3cSBarry Smith }
5315681b3cSBarry Smith 
54d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackViewSAWs(void)
55d71ae5a4SJacob Faibussowitsch {
56d45a07a7SBarry Smith   PetscMPIInt rank;
5715681b3cSBarry Smith 
589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
593ba16761SJacob Faibussowitsch   if (rank) return PETSC_SUCCESS;
6027104ee2SJacob Faibussowitsch   #if PetscDefined(USE_DEBUG)
61792fecdfSBarry Smith   PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/functions", petscstack.function, 20, SAWs_READ, SAWs_STRING));
62792fecdfSBarry Smith   PetscCallSAWs(SAWs_Register, ("/PETSc/Stack/__current_size", &petscstack.currentsize, 1, SAWs_READ, SAWs_INT));
6327104ee2SJacob Faibussowitsch   #endif
642657e9d9SBarry Smith   amsmemstack = PETSC_TRUE;
653ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
6615681b3cSBarry Smith }
6715681b3cSBarry Smith 
68d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackSAWsViewOff(void)
69d71ae5a4SJacob Faibussowitsch {
70d9262e54SJed Brown   PetscFunctionBegin;
713ba16761SJacob Faibussowitsch   if (!amsmemstack) PetscFunctionReturn(PETSC_SUCCESS);
72792fecdfSBarry Smith   PetscCallSAWs(SAWs_Delete, ("/PETSc/Stack"));
732657e9d9SBarry Smith   amsmemstack = PETSC_FALSE;
743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
75d9262e54SJed Brown }
7627104ee2SJacob Faibussowitsch #endif /* PETSC_HAVE_SAWS */
77d9262e54SJed Brown 
78dfb7d7afSStefano Zampini #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
79d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackSetCheck(PetscBool check)
80d71ae5a4SJacob Faibussowitsch {
8127104ee2SJacob Faibussowitsch   petscstack.check = check;
823ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
837fdeb8b9SBarry Smith }
8415681b3cSBarry Smith 
85d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackReset(void)
86d71ae5a4SJacob Faibussowitsch {
8727104ee2SJacob Faibussowitsch   memset(&petscstack, 0, sizeof(petscstack));
883ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
8974b43855SShri Abhyankar }
9074b43855SShri Abhyankar 
91*25073096SBarry Smith // PetscClangLinter pragma disable: -fdoc-sowing-chars
9210450e9eSJacob Faibussowitsch /*
93586f9135SBarry Smith   PetscStackView - Print the current (default) PETSc stack to an ASCII file
94586f9135SBarry Smith 
95586f9135SBarry Smith   Not Collective
96586f9135SBarry Smith 
97586f9135SBarry Smith   Input Parameter:
98586f9135SBarry Smith . file - the file pointer, or `NULL` to use `PETSC_STDOUT`
99586f9135SBarry Smith 
100586f9135SBarry Smith   Level: developer
101586f9135SBarry Smith 
102586f9135SBarry Smith   Notes:
10310450e9eSJacob Faibussowitsch   In debug mode PETSc maintains a stack of the current function calls that can be used to help
10410450e9eSJacob Faibussowitsch   to quickly see where a problem has occurred, for example, when a signal is received. It is
10510450e9eSJacob Faibussowitsch   recommended to use the debugger if extensive information is needed to help debug the problem.
106586f9135SBarry Smith 
107586f9135SBarry Smith   The default stack is a global variable called `petscstack`.
108586f9135SBarry Smith 
109586f9135SBarry Smith .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackPrint()`, `PetscStackSAWsGrantAccess()`, `PetscStackSAWsTakeAccess()`
11010450e9eSJacob Faibussowitsch */
111d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackView(FILE *file)
112d71ae5a4SJacob Faibussowitsch {
113639ff905SBarry Smith   if (!file) file = PETSC_STDOUT;
11427104ee2SJacob Faibussowitsch   if (petscstack.currentsize < 0) {
11527104ee2SJacob Faibussowitsch     /* < 0 is absolutely a corrupted stack, but this function is usually called in an error
11627104ee2SJacob Faibussowitsch      * handler, which are not capable of recovering from errors so best we can do is print
11727104ee2SJacob Faibussowitsch      * this warning */
11827104ee2SJacob Faibussowitsch     fprintf(file, "PetscStack is definitely corrupted with stack size %d\n", petscstack.currentsize);
11927104ee2SJacob Faibussowitsch   } else if (petscstack.currentsize == 0) {
120d9262e54SJed Brown     if (file == PETSC_STDOUT) {
1213ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("No error traceback is available, the problem could be in the main program. \n"));
1226d07e311SBarry Smith     } else {
1237a746cd8SPierre Jolivet       fprintf(file, "No error traceback is available, the problem could be in the main program. \n");
1246d07e311SBarry Smith     }
1256d07e311SBarry Smith   } else {
126bbcf679cSJacob Faibussowitsch     char *ptr = NULL;
127ef1023bdSBarry Smith 
1286d07e311SBarry Smith     if (file == PETSC_STDOUT) {
1293ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("The line numbers in the error traceback are not always exact.\n"));
13027104ee2SJacob Faibussowitsch       for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
1313ba16761SJacob Faibussowitsch         if (petscstack.file[i]) PetscCall((*PetscErrorPrintf)("#%d %s() at %s:%d\n", j, petscstack.function[i], PetscCIFilename(petscstack.file[i]), PetscCILinenumber(petscstack.line[i])));
132ef1023bdSBarry Smith         else {
1333ba16761SJacob Faibussowitsch           PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
1343ba16761SJacob Faibussowitsch           if (!ptr) PetscCall((*PetscErrorPrintf)("#%d %s()\n", j, petscstack.function[i]));
1353ba16761SJacob Faibussowitsch           else PetscCall((*PetscErrorPrintf)("#%d %s\n", j, petscstack.function[i]));
136ef1023bdSBarry Smith         }
13727104ee2SJacob Faibussowitsch       }
138d9262e54SJed Brown     } else {
139660278c0SBarry Smith       fprintf(file, "The line numbers in the error traceback are not always exact.\n");
14027104ee2SJacob Faibussowitsch       for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
141660278c0SBarry Smith         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]));
142ef1023bdSBarry Smith         else {
1433ba16761SJacob Faibussowitsch           PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
144ef1023bdSBarry Smith           if (!ptr) fprintf(file, "[%d] #%d %s()\n", PetscGlobalRank, j, petscstack.function[i]);
145ef1023bdSBarry Smith           else fprintf(file, "[%d] #%d %s\n", PetscGlobalRank, j, petscstack.function[i]);
146ef1023bdSBarry Smith         }
147d9262e54SJed Brown       }
1486d07e311SBarry Smith     }
1497d5f7e0cSShri Abhyankar   }
1503ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
151d9262e54SJed Brown }
152d9262e54SJed Brown 
15310450e9eSJacob Faibussowitsch /*
154586f9135SBarry Smith   PetscStackCopy - Copy the information from one PETSc stack to another
155586f9135SBarry Smith 
156586f9135SBarry Smith   Not Collective
157586f9135SBarry Smith 
158586f9135SBarry Smith   Input Parameter:
159586f9135SBarry Smith . sint - the stack to be copied from
160586f9135SBarry Smith 
161586f9135SBarry Smith   Output Parameter:
162586f9135SBarry Smith . sout - the stack to be copied to, this stack must already exist
163586f9135SBarry Smith 
164586f9135SBarry Smith   Level: developer
165586f9135SBarry Smith 
166811af0c4SBarry Smith   Note:
16710450e9eSJacob Faibussowitsch   In debug mode PETSc maintains a stack of the current function calls that can be used to help
16810450e9eSJacob Faibussowitsch   to quickly see where a problem has occurred, for example, when a signal is received. It is
16910450e9eSJacob Faibussowitsch   recommended to use the debugger if extensive information is needed to help debug the problem.
170586f9135SBarry Smith 
171586f9135SBarry Smith .seealso: `PetscAttachDebugger()`, `PetscStackView()`
17210450e9eSJacob Faibussowitsch */
173d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackCopy(PetscStack *sint, PetscStack *sout)
174d71ae5a4SJacob Faibussowitsch {
17527104ee2SJacob Faibussowitsch   if (sint) {
17627104ee2SJacob Faibussowitsch     for (int i = 0; i < sint->currentsize; ++i) {
177d9262e54SJed Brown       sout->function[i]     = sint->function[i];
178d9262e54SJed Brown       sout->file[i]         = sint->file[i];
179d9262e54SJed Brown       sout->line[i]         = sint->line[i];
180a8d2bbe5SBarry Smith       sout->petscroutine[i] = sint->petscroutine[i];
181d9262e54SJed Brown     }
182d9262e54SJed Brown     sout->currentsize = sint->currentsize;
18327104ee2SJacob Faibussowitsch   } else {
18427104ee2SJacob Faibussowitsch     sout->currentsize = 0;
185d9262e54SJed Brown   }
1863ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
187d9262e54SJed Brown }
188d9262e54SJed Brown 
189*25073096SBarry Smith // PetscClangLinter pragma disable: -fdoc-sowing-chars
19010450e9eSJacob Faibussowitsch /*
191586f9135SBarry Smith   PetscStackPrint - Prints a given PETSc stack to an ASCII file
192586f9135SBarry Smith 
193586f9135SBarry Smith   Not Collective
194586f9135SBarry Smith 
195586f9135SBarry Smith   Input Parameters:
196586f9135SBarry Smith + sint - the PETSc stack to print
197*25073096SBarry Smith - fp   - the file pointer
198586f9135SBarry Smith 
199586f9135SBarry Smith   Level: developer
200586f9135SBarry Smith 
201586f9135SBarry Smith   Notes:
20210450e9eSJacob Faibussowitsch   In debug mode PETSc maintains a stack of the current function calls that can be used to help
20310450e9eSJacob Faibussowitsch   to quickly see where a problem has occurred, for example, when a signal is received. It is
20410450e9eSJacob Faibussowitsch   recommended to use the debugger if extensive information is needed to help debug the problem.
205586f9135SBarry Smith 
206586f9135SBarry Smith   The default stack is a global variable called `petscstack`.
207586f9135SBarry Smith 
208586f9135SBarry Smith   Developer Note:
209586f9135SBarry Smith   `PetscStackPrint()` and `PetscStackView()` should be merged into a single API.
210586f9135SBarry Smith 
211586f9135SBarry Smith .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()`
21210450e9eSJacob Faibussowitsch */
213d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackPrint(PetscStack *sint, FILE *fp)
214d71ae5a4SJacob Faibussowitsch {
21527104ee2SJacob Faibussowitsch   if (sint) {
21627104ee2SJacob Faibussowitsch     for (int i = sint->currentsize - 2; i >= 0; --i) {
217660278c0SBarry Smith       if (sint->file[i]) fprintf(fp, "      [%d]  %s() at %s:%d\n", PetscGlobalRank, sint->function[i], PetscCIFilename(sint->file[i]), PetscCILinenumber(sint->line[i]));
218ef1023bdSBarry Smith       else fprintf(fp, "      [%d]  %s()\n", PetscGlobalRank, sint->function[i]);
21927104ee2SJacob Faibussowitsch     }
22027104ee2SJacob Faibussowitsch   }
2213ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
222d9262e54SJed Brown }
22327104ee2SJacob Faibussowitsch #endif /* PetscDefined(USE_DEBUG) */
224