μHAL (v2.6.5)
Part of the IPbus software repository
exception.cpp
Go to the documentation of this file.
1 /*
2 ---------------------------------------------------------------------------
3 
4  This file is part of uHAL.
5 
6  uHAL is a hardware access library and programming framework
7  originally developed for upgrades of the Level-1 trigger of the CMS
8  experiment at CERN.
9 
10  uHAL is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  uHAL is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with uHAL. If not, see <http://www.gnu.org/licenses/>.
22 
23 
24  Andrew Rose, Imperial College, London
25  email: awr01 <AT> imperial.ac.uk
26 
27  Marc Magrans de Abril, CERN
28  email: marc.magrans.de.abril <AT> cern.ch
29 
30 ---------------------------------------------------------------------------
31 */
32 
39 #include "uhal/log/exception.hpp"
40 
41 
42 #include <cstring>
43 #include <iostream>
44 #include <sstream>
45 #include <stdlib.h>
46 
47 #ifdef USE_BACKTRACE
50 #endif
51 
52 
53 
54 namespace uhal
55 {
56  namespace exception
57  {
58 
59  exception::exception ( ) :
60  std::exception (),
61 #ifdef USE_BACKTRACE
62  mBacktrace ( MaxExceptionHistoryLength , static_cast<void*> ( NULL ) ),
63  mThreadId ( boost::this_thread::get_id() ),
64 #endif
65  mString ( ( char* ) malloc ( 65536 ) ),
66  mAdditionalInfo ( ( char* ) malloc ( 65536 ) )
67  {
68  gettimeofday ( &mTime, NULL );
69 #ifdef USE_BACKTRACE
70  Backtrace::Backtrace ( mBacktrace );
71 #endif
72  mAdditionalInfo[0] = '\0'; //malloc is not required to initialize to null, so do it manually, just in case
73  }
74 
75 
76  exception::exception ( const exception& aExc ) :
77  std::exception (),
78 #ifdef USE_BACKTRACE
79  mBacktrace ( aExc.mBacktrace ),
80  mThreadId ( aExc.mThreadId ),
81 #endif
82  mTime ( aExc.mTime ),
83  mString ( ( char* ) malloc ( 65536 ) ),
84  mAdditionalInfo ( ( char* ) malloc ( 65536 ) )
85  {
86  strcpy ( mAdditionalInfo , aExc.mAdditionalInfo );
87  }
88 
89  exception& exception::operator= ( const exception& aExc )
90  {
91  strcpy ( mAdditionalInfo , aExc.mAdditionalInfo );
92 #ifdef USE_BACKTRACE
93  mBacktrace = aExc.mBacktrace;
94  mThreadId = aExc.mThreadId;
95 #endif
96  mTime = aExc.mTime;
97  return *this;
98  }
99 
100  exception::~exception() throw()
101  {
102  if ( mString )
103  {
104  free ( mString );
105  mString = NULL;
106  }
107 
108  if ( mAdditionalInfo )
109  {
110  free ( mAdditionalInfo );
111  mAdditionalInfo = NULL;
112  }
113  }
114 
115 
116  const char* exception::what() const throw()
117  {
118  if ( mString == NULL )
119  {
120  std::cout << "Could not allocate memory for exception message" << std::endl;
121  return mString;
122  }
123 
124  std::stringstream lStr;
125 
126 #ifdef USE_BACKTRACE
127 
128  timeval lTime;
129  gettimeofday ( &lTime, NULL );
130  lStr << "\n";
131 #ifdef COURTEOUS_EXCEPTIONS
132  lStr << "I'm terribly sorry to have to tell you this, but it appears that there was an exception:\n";
133 #endif
134  lStr << " * Exception type: ";
135 #ifdef __GNUG__
136  // this is fugly but necessary due to the way that typeid::name() returns the object type name under g++.
137  int lStatus ( 0 );
138  std::size_t lSize ( 1024 );
139  char lDemangled[lSize];
140  lStr << abi::__cxa_demangle ( typeid ( *this ).name() , lDemangled , &lSize , &lStatus );
141 #else
142  lStr << typeid ( *this ).name();
143 #endif
144  lStr << "\n";
145  lStr << " * Description: " << description() << "\n";
146 
147  if ( strlen ( mAdditionalInfo ) )
148  {
149  lStr << " * Additional Information:\n";
150  lStr << mAdditionalInfo;
151  }
152 
153  boost::thread::id lThreadId ( boost::this_thread::get_id() );
154 
155  if ( mThreadId == lThreadId )
156  {
157  lStr << " * Exception occured in the same thread as that in which it was caught (" << lThreadId << ")\n";
158  }
159  else
160  {
161  lStr << " * Exception occured in thread with ID: " << mThreadId << "\n";
162  lStr << " * Current thread has ID: " << lThreadId << "\n";
163  }
164 
165  lStr << std::setfill ( '0' );
166  char tmbuf[64];
167  strftime ( tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", localtime ( &mTime.tv_sec ) );
168  lStr << " * Exception constructed at time: " << tmbuf << '.' << std::setw ( 6 ) << mTime.tv_usec << "\n";
169  strftime ( tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", localtime ( &lTime.tv_sec ) );
170  lStr << " * Exception's what() function called at time: " << tmbuf << '.' << std::setw ( 6 ) << lTime.tv_usec << "\n";
171 
172  lStr << " * Call stack:\n";
173  std::vector< Backtrace::TracePoint > lBacktrace = Backtrace::BacktraceSymbols ( mBacktrace );
174  uint32_t lCounter ( 0 );
175  GccOutputCleaner lOutputCleaner ( 12 , &GccOutputCleaner::TStyle );
176 
177  for ( std::vector< Backtrace::TracePoint >::iterator lIt = lBacktrace.begin() +3 ; lIt != lBacktrace.end(); ++lIt , ++lCounter )
178  {
179  lStr << " [ " << std::setw ( 2 ) << lCounter << " ] " << lOutputCleaner ( lIt->function ) << "\n";
180  lStr << " at " << lIt->file << ":" << lIt->line << "\n";
181  }
182 
183 #else
184 
185  if ( strlen ( mAdditionalInfo ) )
186  {
187  lStr << mAdditionalInfo;
188  }
189  else
190  {
191  lStr << description() << " (no additional info)";
192  }
193 
194 #endif
195 
196  std::string lString ( lStr.str() );
197  strncpy ( mString , lString.c_str() , 65536 );
198 
199  if ( lString.size() > 65536 )
200  {
201  strcpy ( mString+65530 , "..." );
202  }
203 
204  return mString;
205  }
206 
207 
208  void exception::append ( const char* aCStr ) throw()
209  {
210  strncat ( mAdditionalInfo, aCStr , 65536-strlen ( mAdditionalInfo ) );
211  }
212 
213  }
214 }
215 
216 
217 
static std::string TStyle(const uint32_t &aIndex)
Prefix the type-substitution index with a T
An abstract base exception class providing an interface to a throw/ThrowAsDerivedType mechanism which...
Definition: exception.hpp:89
Parameterized Functor which parses and formats GCC call stack so that they are human readable...