Flow123d
exceptions.cc
Go to the documentation of this file.
1 /*
2  * exceptions.cc
3  *
4  * Created on: May 9, 2012
5  * Author: jb
6  */
7 
8 #include "system.hh"
9 #include "exceptions.hh"
10 #include <iostream>
11 #include <cstring>
12 #include <boost/exception/diagnostic_information.hpp>
13 
14 #ifdef HAVE_EXEC_INFO
15 #include <execinfo.h>
16 #endif
17 
18 #ifdef HAVE_DEMAGLER
19 #include <cxxabi.h>
20 #endif
21 
23 : stacktrace(NULL),n_stacktrace_frames(0)
24 {
26 }
27 
28 
29 
31 : stacktrace(NULL), n_stacktrace_frames( other.n_stacktrace_frames)
32 {
33  int size=0;
34  for(int i=0; i<n_stacktrace_frames; i++) size+=strlen(other.stacktrace[i])+1;
35  stacktrace = (char **) malloc(size*sizeof(char) +( n_stacktrace_frames+1)*sizeof(stacktrace) );
36  char *ptr_dest = (char *)(stacktrace + n_stacktrace_frames);
37  for(int i=0; i<n_stacktrace_frames; i++) {
38  stacktrace[i]=ptr_dest;
39  char * ptr_src = other.stacktrace[i];
40  while(*ptr_src!=0) *(ptr_dest++) = *(ptr_src++);
41  *(ptr_dest++)=0;
42  }
43 }
44 
45 
46 
47 
49  //DBGMSG("st: %p %p %d\n", this, stacktrace, n_stacktrace_frames);
50  if (stacktrace) {
51  free(stacktrace);
52  stacktrace=NULL;
54  //DBGMSG("st: %p %p %d\n", this, stacktrace, n_stacktrace_frames);
55  }
56 }
57 
58 
60 {
61 #ifdef HAVE_EXEC_INFO
62  if (! stacktrace && ! n_stacktrace_frames) {
63  void * array[25];
64  n_stacktrace_frames = backtrace(array, 25);
65  stacktrace = backtrace_symbols(array, n_stacktrace_frames);
66  //DBGMSG("st: %p %p %d\n", this, stacktrace, n_stacktrace_frames);
67  }
68 #endif
69 }
70 
71 
72 
73 
74 
75 
76 
77 
78 void ExceptionBase::print_stacktrace(std::ostream &out) const {
79  out << endl;
80  out << "** Stacktrace **" << endl;
81 
82  int i_frame;
83  for(i_frame=0; i_frame < n_stacktrace_frames; i_frame++) {
84  string frame(stacktrace[i_frame]);
85  if ( frame.find("boost") != string::npos
86  && frame.find("exception_detail") != string::npos
87  && frame.find("throw_exception") != string::npos
88  ) break;
89  }
90  i_frame++;
91 
92  unsigned int out_i_frame=0;
93  for(;i_frame< n_stacktrace_frames; i_frame++, out_i_frame++) {
94  string frame(stacktrace[i_frame]);
95  unsigned int start_pos = frame.find("(")+1,
96  end_pos = frame.find("+");
97  string magled_fname = frame.substr( start_pos, end_pos-start_pos );
98 
99  int status=-1;
100  char *demagled_f_name;
101 
102 #ifdef HAVE_DEMAGLER
103  demagled_f_name = abi::__cxa_demangle(magled_fname.c_str(), 0, 0, &status);
104 #endif
105  if (status == 0) {
106  out << setw(3) << out_i_frame << " " << demagled_f_name << endl;
107  free(demagled_f_name);
108  } else {
109  out << setw(3) << out_i_frame << " " << magled_fname << endl;
110  }
111 
112  if (magled_fname == "main") break;
113  }
114  out << endl;
115 
116 }
117 
118 
119 const char * ExceptionBase::what() const throw () {
120  // have preallocated some space for error message we want to return
121  // Is there any difference, if we move this into ExceptionBase ??
122  static std::string message(1024,' ');
123 
124  // Be sure that this function do not throw.
125  try {
126  std::ostringstream converter;
127 
128  converter << std::endl << std::endl;
129  converter << "--------------------------------------------------------" << std::endl;
130  converter << "Program Error: ";
131  print_info(converter);
132 
133  converter << "\n** Diagnosting info **\n" ;
134  converter << boost::diagnostic_information_what( *this );
135  print_stacktrace(converter);
136  converter << "--------------------------------------------------------" << std::endl;
137 
138  message = converter.str();
139  return message.c_str();
140 
141  } catch (std::exception &exc) {
142  std::cerr << "*** Exception encountered in exception handling routines ***" << std::endl << "*** Message is " << std::endl
143  << exc.what() << std::endl << "*** Aborting! ***" << std::endl;
144 
145  std::abort();
146  } catch (...) {
147  std::cerr << "*** Exception encountered in exception handling routines ***" << std::endl << "*** Aborting! ***"
148  << std::endl;
149 
150  std::abort();
151  }
152  return 0;
153 }
154 
155 
156