Flow123d  jenkins-Flow123d-linux-release-multijob-282
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  if (stacktrace) {
50  free(stacktrace);
51  stacktrace=NULL;
53  }
54 }
55 
56 
58 {
59 #ifdef HAVE_EXEC_INFO
60  if (! stacktrace && ! n_stacktrace_frames) {
61  void * array[25];
62  n_stacktrace_frames = backtrace(array, 25);
63  stacktrace = backtrace_symbols(array, n_stacktrace_frames);
64  }
65 #endif
66 }
67 
68 
69 
70 
71 
72 
73 
74 
75 void ExceptionBase::print_stacktrace(std::ostream &out) const {
76  out << endl;
77  out << "** Stacktrace **" << endl;
78 
79  int i_frame;
80  for(i_frame=0; i_frame < n_stacktrace_frames; i_frame++) {
81  string frame(stacktrace[i_frame]);
82  if ( frame.find("boost") != string::npos
83  && frame.find("exception_detail") != string::npos
84  && frame.find("throw_exception") != string::npos
85  ) break;
86  }
87  i_frame++;
88 
89  unsigned int out_i_frame=0;
90  for(;i_frame< n_stacktrace_frames; i_frame++, out_i_frame++) {
91  string frame(stacktrace[i_frame]);
92  unsigned int start_pos = frame.find("(")+1,
93  end_pos = frame.find("+");
94  string magled_fname = frame.substr( start_pos, end_pos-start_pos );
95 
96  int status=-1;
97  char *demagled_f_name = {0};
98 
99 #ifdef HAVE_DEMAGLER
100  demagled_f_name = abi::__cxa_demangle(magled_fname.c_str(), 0, 0, &status);
101 #endif
102  if (status == 0) {
103  out << setw(3) << out_i_frame << " " << demagled_f_name << endl;
104  free(demagled_f_name);
105  } else {
106  out << setw(3) << out_i_frame << " " << magled_fname << endl;
107  }
108 
109  if (magled_fname == "main") break;
110  }
111  out << endl;
112 
113 }
114 
115 
116 const char * ExceptionBase::what() const throw () {
117  // have preallocated some space for error message we want to return
118  // Is there any difference, if we move this into ExceptionBase ??
119  static std::string message(1024,' ');
120 
121  // Be sure that this function do not throw.
122  try {
123  std::ostringstream converter;
124 
125  converter << std::endl << std::endl;
126  converter << "--------------------------------------------------------" << std::endl;
127  converter << "Program Error: ";
128  print_info(converter);
129 
130  converter << "\n** Diagnosting info **\n" ;
131  converter << boost::diagnostic_information_what( *this );
132  print_stacktrace(converter);
133  converter << "--------------------------------------------------------" << std::endl;
134 
135  message = converter.str();
136  return message.c_str();
137 
138  } catch (std::exception &exc) {
139  std::cerr << "*** Exception encountered in exception handling routines ***" << std::endl << "*** Message is " << std::endl
140  << exc.what() << std::endl << "*** Aborting! ***" << std::endl;
141 
142  std::abort();
143  } catch (...) {
144  std::cerr << "*** Exception encountered in exception handling routines ***" << std::endl << "*** Aborting! ***"
145  << std::endl;
146 
147  std::abort();
148  }
149  return 0;
150 }
151 
152 
153 
virtual const char * what() const
Definition: exceptions.cc:116
ExceptionBase()
Default constructor, just calls fill_stacktrace().
Definition: exceptions.cc:22
void fill_stacktrace()
Call GNU backtrace if available, save call stack information into stacktrace member.
Definition: exceptions.cc:57
virtual ~ExceptionBase()
Destructor, possibly free stacktrace.
Definition: exceptions.cc:48
Base of exceptions used in Flow123d.
Definition: exceptions.hh:55
char ** stacktrace
Array of backtrace frames returned by glibc backtrace_symbols.
Definition: exceptions.hh:83
void print_stacktrace(std::ostream &out) const
Prints formated stacktrace into given stream out.
Definition: exceptions.cc:75
int n_stacktrace_frames
Size of stacktrace table - number of frames.
Definition: exceptions.hh:86
virtual void print_info(std::ostringstream &out) const =0