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
125d83a8b1SBarry Smith /*@
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:
2054c05997SPierre Jolivet Cannot use `PetscFunctionBegin`/`PetscFunctionReturn()` or `PetscCallSAWs()` since it may be
2110450e9eSJacob Faibussowitsch used within those routines
2215681b3cSBarry Smith
23db781477SPatrick Sanan .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()`
2415681b3cSBarry Smith @*/
PetscStackSAWsGrantAccess(void)25d71ae5a4SJacob Faibussowitsch void PetscStackSAWsGrantAccess(void)
26d71ae5a4SJacob Faibussowitsch {
27ec957eceSBarry Smith if (amsmemstack) {
2816ad0300SBarry Smith /* ignore any errors from SAWs */
29dd460d27SBarry Smith (void)SAWs_Unlock();
3015681b3cSBarry Smith }
31d9262e54SJed Brown }
32d9262e54SJed Brown
335d83a8b1SBarry Smith /*@
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 @*/
PetscStackSAWsTakeAccess(void)46d71ae5a4SJacob Faibussowitsch void PetscStackSAWsTakeAccess(void)
47d71ae5a4SJacob Faibussowitsch {
48ec957eceSBarry Smith if (amsmemstack) {
4916ad0300SBarry Smith /* ignore any errors from SAWs */
50dd460d27SBarry Smith (void)SAWs_Lock();
5115681b3cSBarry Smith }
5215681b3cSBarry Smith }
5315681b3cSBarry Smith
PetscStackViewSAWs(void)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
PetscStackSAWsViewOff(void)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)
PetscStackSetCheck(PetscBool check)79d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackSetCheck(PetscBool check)
80d71ae5a4SJacob Faibussowitsch {
8127104ee2SJacob Faibussowitsch petscstack.check = check;
823ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
837fdeb8b9SBarry Smith }
8415681b3cSBarry Smith
PetscStackReset(void)85d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackReset(void)
86d71ae5a4SJacob Faibussowitsch {
8727104ee2SJacob Faibussowitsch memset(&petscstack, 0, sizeof(petscstack));
883ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
8974b43855SShri Abhyankar }
9074b43855SShri Abhyankar
9125073096SBarry 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:
98*67a21fd9SBarry Smith . file - the file pointer, or `NULL` to use `PETSC_STDERR`
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
107*67a21fd9SBarry Smith If `file` is `PETSC_STDERR` (or `NULL`) then `PetscErrorPrintf()` is used to print the stack, otherwise `fprintf()` is used.
108*67a21fd9SBarry Smith
109*67a21fd9SBarry Smith Developer Note:
110586f9135SBarry Smith The default stack is a global variable called `petscstack`.
111586f9135SBarry Smith
112586f9135SBarry Smith .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackPrint()`, `PetscStackSAWsGrantAccess()`, `PetscStackSAWsTakeAccess()`
11310450e9eSJacob Faibussowitsch */
PetscStackView(FILE * file)114d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackView(FILE *file)
115d71ae5a4SJacob Faibussowitsch {
116*67a21fd9SBarry Smith if (!file) file = PETSC_STDERR;
11727104ee2SJacob Faibussowitsch if (petscstack.currentsize < 0) {
11827104ee2SJacob Faibussowitsch /* < 0 is absolutely a corrupted stack, but this function is usually called in an error
11927104ee2SJacob Faibussowitsch * handler, which are not capable of recovering from errors so best we can do is print
12027104ee2SJacob Faibussowitsch * this warning */
12127104ee2SJacob Faibussowitsch fprintf(file, "PetscStack is definitely corrupted with stack size %d\n", petscstack.currentsize);
12227104ee2SJacob Faibussowitsch } else if (petscstack.currentsize == 0) {
123*67a21fd9SBarry Smith if (file == PETSC_STDERR) {
1243ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("No error traceback is available, the problem could be in the main program. \n"));
1256d07e311SBarry Smith } else {
1267a746cd8SPierre Jolivet fprintf(file, "No error traceback is available, the problem could be in the main program. \n");
1276d07e311SBarry Smith }
1286d07e311SBarry Smith } else {
129bbcf679cSJacob Faibussowitsch char *ptr = NULL;
130ef1023bdSBarry Smith
131*67a21fd9SBarry Smith if (file == PETSC_STDERR) {
1329c9354e5SBarry Smith PetscCall((*PetscErrorPrintf)("The line numbers in the error traceback may not be exact.\n"));
13327104ee2SJacob Faibussowitsch for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
1343ba16761SJacob 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])));
135ef1023bdSBarry Smith else {
1363ba16761SJacob Faibussowitsch PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
1373ba16761SJacob Faibussowitsch if (!ptr) PetscCall((*PetscErrorPrintf)("#%d %s()\n", j, petscstack.function[i]));
1383ba16761SJacob Faibussowitsch else PetscCall((*PetscErrorPrintf)("#%d %s\n", j, petscstack.function[i]));
139ef1023bdSBarry Smith }
14027104ee2SJacob Faibussowitsch }
141d9262e54SJed Brown } else {
142660278c0SBarry Smith fprintf(file, "The line numbers in the error traceback are not always exact.\n");
14327104ee2SJacob Faibussowitsch for (int i = petscstack.currentsize - 1, j = 1; i >= 0; --i, ++j) {
144660278c0SBarry 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]));
145ef1023bdSBarry Smith else {
1463ba16761SJacob Faibussowitsch PetscCall(PetscStrstr(petscstack.function[i], " ", &ptr));
147ef1023bdSBarry Smith if (!ptr) fprintf(file, "[%d] #%d %s()\n", PetscGlobalRank, j, petscstack.function[i]);
148ef1023bdSBarry Smith else fprintf(file, "[%d] #%d %s\n", PetscGlobalRank, j, petscstack.function[i]);
149ef1023bdSBarry Smith }
150d9262e54SJed Brown }
1516d07e311SBarry Smith }
1527d5f7e0cSShri Abhyankar }
1533ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
154d9262e54SJed Brown }
155d9262e54SJed Brown
15610450e9eSJacob Faibussowitsch /*
157586f9135SBarry Smith PetscStackCopy - Copy the information from one PETSc stack to another
158586f9135SBarry Smith
159586f9135SBarry Smith Not Collective
160586f9135SBarry Smith
161586f9135SBarry Smith Input Parameter:
162586f9135SBarry Smith . sint - the stack to be copied from
163586f9135SBarry Smith
164586f9135SBarry Smith Output Parameter:
165586f9135SBarry Smith . sout - the stack to be copied to, this stack must already exist
166586f9135SBarry Smith
167586f9135SBarry Smith Level: developer
168586f9135SBarry Smith
169811af0c4SBarry Smith Note:
17010450e9eSJacob Faibussowitsch In debug mode PETSc maintains a stack of the current function calls that can be used to help
17110450e9eSJacob Faibussowitsch to quickly see where a problem has occurred, for example, when a signal is received. It is
17210450e9eSJacob Faibussowitsch recommended to use the debugger if extensive information is needed to help debug the problem.
173586f9135SBarry Smith
174586f9135SBarry Smith .seealso: `PetscAttachDebugger()`, `PetscStackView()`
17510450e9eSJacob Faibussowitsch */
PetscStackCopy(PetscStack * sint,PetscStack * sout)176d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackCopy(PetscStack *sint, PetscStack *sout)
177d71ae5a4SJacob Faibussowitsch {
17827104ee2SJacob Faibussowitsch if (sint) {
17927104ee2SJacob Faibussowitsch for (int i = 0; i < sint->currentsize; ++i) {
180d9262e54SJed Brown sout->function[i] = sint->function[i];
181d9262e54SJed Brown sout->file[i] = sint->file[i];
182d9262e54SJed Brown sout->line[i] = sint->line[i];
183a8d2bbe5SBarry Smith sout->petscroutine[i] = sint->petscroutine[i];
184d9262e54SJed Brown }
185d9262e54SJed Brown sout->currentsize = sint->currentsize;
18627104ee2SJacob Faibussowitsch } else {
18727104ee2SJacob Faibussowitsch sout->currentsize = 0;
188d9262e54SJed Brown }
1893ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
190d9262e54SJed Brown }
191d9262e54SJed Brown
19225073096SBarry Smith // PetscClangLinter pragma disable: -fdoc-sowing-chars
19310450e9eSJacob Faibussowitsch /*
194586f9135SBarry Smith PetscStackPrint - Prints a given PETSc stack to an ASCII file
195586f9135SBarry Smith
196586f9135SBarry Smith Not Collective
197586f9135SBarry Smith
198586f9135SBarry Smith Input Parameters:
199586f9135SBarry Smith + sint - the PETSc stack to print
20025073096SBarry Smith - fp - the file pointer
201586f9135SBarry Smith
202586f9135SBarry Smith Level: developer
203586f9135SBarry Smith
204586f9135SBarry Smith Notes:
20510450e9eSJacob Faibussowitsch In debug mode PETSc maintains a stack of the current function calls that can be used to help
20610450e9eSJacob Faibussowitsch to quickly see where a problem has occurred, for example, when a signal is received. It is
20710450e9eSJacob Faibussowitsch recommended to use the debugger if extensive information is needed to help debug the problem.
208586f9135SBarry Smith
209586f9135SBarry Smith The default stack is a global variable called `petscstack`.
210586f9135SBarry Smith
211586f9135SBarry Smith Developer Note:
212586f9135SBarry Smith `PetscStackPrint()` and `PetscStackView()` should be merged into a single API.
213586f9135SBarry Smith
214586f9135SBarry Smith .seealso: `PetscAttachDebugger()`, `PetscStackCopy()`, `PetscStackView()`
21510450e9eSJacob Faibussowitsch */
PetscStackPrint(PetscStack * sint,FILE * fp)216d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStackPrint(PetscStack *sint, FILE *fp)
217d71ae5a4SJacob Faibussowitsch {
21827104ee2SJacob Faibussowitsch if (sint) {
2199c9354e5SBarry Smith for (int i = sint->currentsize; i >= 0; --i) {
220660278c0SBarry 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]));
221ef1023bdSBarry Smith else fprintf(fp, " [%d] %s()\n", PetscGlobalRank, sint->function[i]);
22227104ee2SJacob Faibussowitsch }
22327104ee2SJacob Faibussowitsch }
2243ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
225d9262e54SJed Brown }
22627104ee2SJacob Faibussowitsch #endif /* PetscDefined(USE_DEBUG) */
227