Diana Software
QDianaDebug.cc
Go to the documentation of this file.
1 #include "QDianaDebug.hh"
2 #include "QDemangle.hh"
3 #include "QError.hh"
4 #include <sstream>
5 #include <sys/ioctl.h>
6 #include <stdlib.h>
7 #include <execinfo.h>
8 #include <cxxabi.h>
9 
10 #ifdef __BACKTRACE_ON__
11 #include <TSystem.h>
12 #endif
13 
14 namespace Diana {
15 
16  bool DianaDebug = true;
17 
18  void SetDianaDebug(bool value) { DianaDebug = value; }
19 
20  bool GetDianaDebug() { return DianaDebug; }
21 
22 
23  void Abort(const QError& err)
24  {
25  std::stringstream errstr;
26  errstr << "Abort: "<<std::endl
27  << "Q> Exception: QError" << std::endl
28  << "Q> Code : " << (int)err.GetCode()
29  << " (" << err.ToString() << ")";
30  if("" != err.GetDescription()) {
31  errstr << std::endl<<"Q> Descr : " << err.GetDescription();
32  }
33  std::cerr<<errstr.str()<<std::endl;
34  diana_stacktrace(std::cerr);
35  std::cerr << std::flush;
36  abort();
37  }
38 
39  void Abort(std::exception& ex)
40  {
41  std::stringstream errstr;
42  errstr << "Abort: "<<std::endl
43  <<"Q> Exception: " << ex.what();
44  std::cerr<<errstr.str()<<std::endl;
45  diana_stacktrace(std::cerr);
46  std::cerr << std::flush;
47  abort();
48  }
49 
50  void Abort(const std::string& str)
51  {
52  std::stringstream errstr;
53  errstr << "Abort: "<<std::endl
54  <<"Q> Exception: " << str;
55  std::cerr<<errstr.str()<<std::endl;
56  diana_stacktrace(std::cerr);
57  std::cerr << std::flush;
58  abort();
59  }
60 
61  void Abort(...)
62  {
63  std::stringstream errstr;
64  errstr << "Error: "<<std::endl
65  << "Q> Exception: Unknown type";
66  std::cerr<<errstr.str()<<std::endl;
67  diana_stacktrace(std::cerr);
68  std::cerr << std::flush;
69  abort();
70  }
71 
72 };
73 
74 void diana_stacktrace(std::ostream &o,size_t MaxLines){
75 #ifdef __BACKTRACE_ON__
76  FILE *tmpFile=tmpfile(); // Create temp file
77  int save_stderr=dup(fileno(stderr)); // Store the fileno for stderr
78  dup2(fileno(tmpFile),fileno(stderr)); // redirect stderr -> tmpFile
79  gSystem->StackTrace(); // Run the stack trace
80  dup2(save_stderr,STDERR_FILENO); // Redirect stderr to where it was
81  rewind(tmpFile); // Rewind the tmp file
82 
83  // output the tmpFile to the stream
84  // Get the window width (silly)
85  struct winsize w;
86  ioctl(0, TIOCGWINSZ, &w);
87  int NCol=w.ws_col;
88  if (NCol < 18) NCol = 18;
89  o << "\n" << std::string((NCol-18)/2,'-') << " DIANA Backtrace: "
90  << std::string((NCol-18)/2,'-') << std::endl;
91  while(!feof(tmpFile)){
92  char c=fgetc(tmpFile);
93  o << c;
94  }
95  o << "\b";
96  o << std::string((NCol-18)/2,'-') << " Finish Backtrace "
97  << std::string((NCol-18)/2,'-') << std::endl;
98 
99  fclose(tmpFile); // close the tmpFile
100 #endif
101 }
102 
103  /*
104  // Get the window width (silly)
105  struct winsize w;
106  ioctl(0, TIOCGWINSZ, &w);
107  int NCol=w.ws_col;
108 
109  o << "DIANA Backtrace: " << std::endl;
110  o << std::string(NCol,'+') << std::endl;
111 
112  MaxLines+=1;
113 
114  void *AddrList[MaxLines];
115 
116  int AddrLen = backtrace(AddrList, MaxLines);
117 
118  if (AddrLen == 0) {
119  o << " <empty, possibly corrupt>" << std::endl;
120  o << std::string(NCol,'+') << std::endl;
121  return;
122  }
123 
124  char **SymbolList = backtrace_symbols(AddrList,AddrLen);
125 
126  size_t maxNameSize = 256;
127  char *FuncName=(char*) malloc(maxNameSize*sizeof(char));
128 
129  for(int i=1;i<AddrLen;i++){
130 
131  char *begin_name = 0, *begin_offset = 0, *end_offset = 0;
132 
133  for (char *p = SymbolList[i]; *p; p++){
134  if (*p == '(')
135  begin_name = p;
136  else if (*p == '+')
137  begin_offset = p;
138  else if (*p == ')' && begin_offset) {
139  end_offset = p;
140  break;
141  }
142  }
143 
144  if (begin_name && begin_offset && end_offset && begin_name < begin_offset){
145  *begin_name++ = '\0';
146  *begin_offset++ = '\0';
147  *end_offset = '\0';
148 
149  int status;
150  // Diana::CAXDemangle doesnt handle spaces in the name properly
151  char* ret = abi::__cxa_demangle(begin_name,
152  FuncName,&maxNameSize,&status);
153 
154  if (status == 0) {
155  FuncName = ret;
156  o << " " << SymbolList[i] << " : " << FuncName << "+"
157  << begin_offset << std::endl;
158  }
159  else {
160  o << " " << SymbolList[i] << " : " << begin_name
161  << begin_offset << std::endl;
162  }
163  }
164  else {
165  o << SymbolList[i] << std::endl;
166  }
167  o << std::string(NCol,'+') << std::endl;
168  }
169 
170  free(FuncName);
171  free(SymbolList);
172 }
173 */
err
Definition: CheckOF.C:114
void diana_stacktrace(std::ostream &o, size_t MaxLines)
Definition: QDianaDebug.cc:74
error class with error type and description
Definition: QError.hh:115
the Diana namespace is needed because sometimes we use Qt libraries, that use same class names of our...
bool GetDianaDebug()
Definition: QDianaDebug.cc:20
bool DianaDebug
Definition: QDianaDebug.cc:16
void Abort(const QError &err)
Definition: QDianaDebug.cc:23
void SetDianaDebug(bool value)
Definition: QDianaDebug.cc:18