xref: /petsc/src/sys/error/pstack.c (revision f97672e55eacc8688507b9471cd7ec2664d7f203)
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 PetscStackCallSAWs() since it may be used within those routines
21 
22 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()`
23 
24 @*/
25 void  PetscStackSAWsGrantAccess(void)
26 {
27   if (amsmemstack) {
28     /* ignore any errors from SAWs */
29     SAWs_Unlock();
30   }
31 }
32 
33 /*@C
34    PetscStackSAWsTakeAccess - Takes access of the PETSc stack frames to the SAWs publisher
35 
36    Collective on PETSC_COMM_WORLD?
37 
38    Level: developer
39 
40    Developers Note: Cannot use PetscFunctionBegin/Return() or PetscStackCallSAWs() since it may be used within those routines
41 
42 .seealso: `PetscObjectSetName()`, `PetscObjectSAWsViewOff()`, `PetscObjectSAWsTakeAccess()`
43 
44 @*/
45 void  PetscStackSAWsTakeAccess(void)
46 {
47   if (amsmemstack) {
48     /* ignore any errors from SAWs */
49     SAWs_Lock();
50   }
51 }
52 
53 PetscErrorCode PetscStackViewSAWs(void)
54 {
55   PetscMPIInt    rank;
56 
57   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank));
58   if (rank) return 0;
59 #if PetscDefined(USE_DEBUG)
60   PetscStackCallSAWs(SAWs_Register,("/PETSc/Stack/functions",petscstack.function,20,SAWs_READ,SAWs_STRING));
61   PetscStackCallSAWs(SAWs_Register,("/PETSc/Stack/__current_size",&petscstack.currentsize,1,SAWs_READ,SAWs_INT));
62 #endif
63   amsmemstack = PETSC_TRUE;
64   return 0;
65 }
66 
67 PetscErrorCode PetscStackSAWsViewOff(void)
68 {
69   PetscFunctionBegin;
70   if (!amsmemstack) PetscFunctionReturn(0);
71   PetscStackCallSAWs(SAWs_Delete,("/PETSc/Stack"));
72   amsmemstack = PETSC_FALSE;
73   PetscFunctionReturn(0);
74 }
75 #endif /* PETSC_HAVE_SAWS */
76 
77 #if PetscDefined(USE_DEBUG)
78 PetscErrorCode PetscStackSetCheck(PetscBool check)
79 {
80   petscstack.check = check;
81   return 0;
82 }
83 
84 PetscErrorCode PetscStackReset(void)
85 {
86   memset(&petscstack,0,sizeof(petscstack));
87   return 0;
88 }
89 
90 PetscErrorCode  PetscStackView(FILE *file)
91 {
92   if (!file) file = PETSC_STDOUT;
93   if (petscstack.currentsize < 0) {
94     /* < 0 is absolutely a corrupted stack, but this function is usually called in an error
95      * handler, which are not capable of recovering from errors so best we can do is print
96      * this warning */
97     fprintf(file,"PetscStack is definitely corrupted with stack size %d\n",petscstack.currentsize);
98   } else if (petscstack.currentsize == 0) {
99     if (file == PETSC_STDOUT) {
100       (*PetscErrorPrintf)("No error traceback is available, the problem could be in the main program. \n");
101     } else {
102       fprintf(file,"No error traceback is available, the problem could be in the main program. \n");
103     }
104   } else {
105     if (file == PETSC_STDOUT) {
106       (*PetscErrorPrintf)("The EXACT line numbers in the error traceback are not available.\n");
107       (*PetscErrorPrintf)("instead the line number of the start of the function is given.\n");
108       for (int i = petscstack.currentsize-1, j = 1; i >= 0; --i, ++j) {
109         (*PetscErrorPrintf)("#%d %s() at %s:%d\n",j,petscstack.function[i],petscstack.file[i],petscstack.line[i]);
110       }
111     } else {
112       fprintf(file,"The EXACT line numbers in the error traceback are not available.\n");
113       fprintf(file,"Instead the line number of the start of the function is given.\n");
114       for (int i = petscstack.currentsize-1, j = 1; i >= 0; --i, ++j) {
115         fprintf(file,"[%d] #%d %s() at %s:%d\n",PetscGlobalRank,j,petscstack.function[i],petscstack.file[i],petscstack.line[i]);
116       }
117     }
118   }
119   return 0;
120 }
121 
122 /*  PetscFunctionBegin;  so that make rule checkbadPetscFunctionBegin works */
123 PetscErrorCode  PetscStackCopy(PetscStack *sint,PetscStack *sout)
124 {
125   if (sint) {
126     for (int i = 0; i < sint->currentsize; ++i) {
127       sout->function[i]     = sint->function[i];
128       sout->file[i]         = sint->file[i];
129       sout->line[i]         = sint->line[i];
130       sout->petscroutine[i] = sint->petscroutine[i];
131     }
132     sout->currentsize = sint->currentsize;
133   } else {
134     sout->currentsize = 0;
135   }
136   return 0;
137 }
138 
139 /*  PetscFunctionBegin;  so that make rule checkbadPetscFunctionBegin works */
140 PetscErrorCode  PetscStackPrint(PetscStack *sint,FILE *fp)
141 {
142   if (sint) {
143     for (int i = sint->currentsize-2; i >= 0; --i) {
144       fprintf(fp,"      [%d]  %s() at %s:%d\n",PetscGlobalRank,sint->function[i],sint->file[i],sint->line[i]);
145     }
146   }
147   return 0;
148 }
149 #endif /* PetscDefined(USE_DEBUG) */
150