CLAM-Development  1.4.0
Assert.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include "Assert.hxx"
23 #include <iostream>
24 #include <cstdlib>
25 #include <csignal>
26 #if defined(__linux__)
27 #include <execinfo.h>
28 #endif
29 
30 #ifdef __GNUC__
31 #include <cxxabi.h> // For demangling symbols
32 #endif//__GNUC__
33 
34 
35 
36 namespace CLAM {
37 
38 // TODO: This code is duplicated in ProcessingDataPlugin.cxx
39 std::string demangleSymbol(const std::string & mangledName)
40 {
41  std::string result=mangledName;
42  #ifdef __GNUC__
43  size_t parenthesisPos = result.find_first_of('(');
44  if (parenthesisPos == std::string::npos) return result;
45  size_t endPos = result.find_first_of("+", parenthesisPos);
46  if (endPos == std::string::npos) endPos = result.find_first_of(")", parenthesisPos);
47  std::string head = result.substr(0,parenthesisPos+1);
48  std::string tail = result.substr(endPos);
49  std::string mangled = result.substr(parenthesisPos+1, endPos-parenthesisPos-1);
50  int demangleError = 0;
51  char * demangled = abi::__cxa_demangle(mangled.c_str(),0,0,&demangleError);
52  if (!demangleError && demangled)
53  result = head+demangled+tail;
54  if (demangled) free(demangled);
55  #endif//__GNUC__
56  return result;
57 }
58 
59 void DumpBacktrace(std::ostream & os)
60 {
61 #if defined(__linux__)
62 
63  void *bt_array[100]; // 100 should be enough ?!?
64  char **bt_strings;
65  int num_entries;
66 
67  if ((num_entries = backtrace(bt_array, 100)) < 0) {
68  os << " Unable to generate a backtrace" << std::endl;
69  return;
70  }
71 
72  if ((bt_strings = backtrace_symbols(bt_array, num_entries)) == NULL) {
73  os << " Unable to adquire symbols names for the backtrace" << std::endl;
74  return;
75  }
76 
77  os << "\n Backtrace:\n" << std::endl;
78  for (int i = 0; i < num_entries; i++) {
79  os << "[" << i << "] " << demangleSymbol(bt_strings[i]) << std::endl;
80  }
81  free(bt_strings);
82 #else
83  os << " Unable to adquire symbols names for the backtrace" << std::endl;
84 #endif
85 }
86 
87 
88 // by default, CLAM asserts must breakpoint
89 // we'll want to disable breakpoints for automatic assertion testing
90 // purposes
92 
93 // Assert related
94 
95 static void DefaultAssertHandler(const char* message, const char* filename, int lineNumber )
96 {
97  std::cerr << "##########################################################" << std::endl;
98  std::cerr << "################### ASSERTION FAILED #####################" << std::endl;
99  std::cerr << "##########################################################" << std::endl;
100  std::cerr << "At file " << filename << " line " << lineNumber << std::endl;
101  std::cerr << message << std::endl;
102  DumpBacktrace(std::cerr);
103 }
104 
106 
109  CurrentAssertFailedHandler = handler;
110  return oldHandler;
111 }
112 
113 void ExecuteAssertFailedHandler(const char* message, const char* filename, int lineNumber )
114 {
115  CurrentAssertFailedHandler(message,filename,lineNumber);
116 }
117 
119 
120 ErrAssertionFailed::ErrAssertionFailed(const char* message, const char* filename, int lineNumber)
121  : Err(message)
122 {
123  if (!breakpointInCLAMAssertEnabled) return;
124 
125  CurrentAssertFailedHandler( message, filename, lineNumber );
126 }
127 
128 // Warning related
129 
130 static void DefaultWarningHandler(const char* message, const char* filename, int lineNumber )
131 {
132  std::cerr << "####### WARNING: At file " << filename << " line " << lineNumber << std::endl;
133  std::cerr << "\033[31m" << message << "\033[0m" << std::endl;
134 }
135 
137 
140  CurrentWarningHandler = handler;
141  return oldHandler;
142 }
143 
144 void ExecuteWarningHandler(const char* message, const char* filename, int lineNumber )
145 {
146  CurrentWarningHandler(message,filename,lineNumber);
147 }
148 
149 #if 0 // defined(__linux__)
150 class SystemSignalTrapper
151 {
152  int _signal;
153  sighandler_t _oldHandler;
154 public:
155  SystemSignalTrapper(int signal, sighandler_t handler) :
156  _signal(signal)
157  {
158  _oldHandler = std::signal(signal, handler);
159  }
160  ~SystemSignalTrapper()
161  {
162  std::signal(_signal, _oldHandler);
163  }
164 };
165 void segvSignalHandler(int myInt)
166 {
167  std::cerr << std::endl;
168  std::cerr << "##########################################################" << std::endl;
169  std::cerr << "#################### BAD MEMORY ACCES ####################" << std::endl;
170  std::cerr << "##########################################################" << std::endl;
171  DumpBacktrace(std::cerr);
172  std::abort();
173 }
174 
175 static SystemSignalTrapper segvSignalTrapper(SIGSEGV,segvSignalHandler);
176 #endif //defined linux
177 
178 
179 }
180 
181