|
CLAM-Development
1.3
|
00001 /* 00002 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #include "Assert.hxx" 00023 #include <iostream> 00024 #include <cstdlib> 00025 #include <csignal> 00026 #if defined(__linux__) 00027 #include <execinfo.h> 00028 #endif 00029 00030 #ifdef __GNUC__ 00031 #include <cxxabi.h> // For demangling symbols 00032 #endif//__GNUC__ 00033 00034 00035 00036 namespace CLAM { 00037 00038 // TODO: This code is duplicated in ProcessingDataPlugin.cxx 00039 std::string demangleSymbol(const std::string & mangledName) 00040 { 00041 std::string result=mangledName; 00042 #ifdef __GNUC__ 00043 size_t parenthesisPos = result.find_first_of('('); 00044 if (parenthesisPos == std::string::npos) return result; 00045 size_t endPos = result.find_first_of("+", parenthesisPos); 00046 if (endPos == std::string::npos) endPos = result.find_first_of(")", parenthesisPos); 00047 std::string head = result.substr(0,parenthesisPos+1); 00048 std::string tail = result.substr(endPos); 00049 std::string mangled = result.substr(parenthesisPos+1, endPos-parenthesisPos-1); 00050 int demangleError = 0; 00051 char * demangled = abi::__cxa_demangle(mangled.c_str(),0,0,&demangleError); 00052 if (!demangleError && demangled) 00053 result = head+demangled+tail; 00054 if (demangled) free(demangled); 00055 #endif//__GNUC__ 00056 return result; 00057 } 00058 00059 void DumpBacktrace(std::ostream & os) 00060 { 00061 #if defined(__linux__) 00062 00063 void *bt_array[100]; // 100 should be enough ?!? 00064 char **bt_strings; 00065 int num_entries; 00066 00067 if ((num_entries = backtrace(bt_array, 100)) < 0) { 00068 os << " Unable to generate a backtrace" << std::endl; 00069 return; 00070 } 00071 00072 if ((bt_strings = backtrace_symbols(bt_array, num_entries)) == NULL) { 00073 os << " Unable to adquire symbols names for the backtrace" << std::endl; 00074 return; 00075 } 00076 00077 os << "\n Backtrace:\n" << std::endl; 00078 for (int i = 0; i < num_entries; i++) { 00079 os << "[" << i << "] " << demangleSymbol(bt_strings[i]) << std::endl; 00080 } 00081 free(bt_strings); 00082 #else 00083 os << " Unable to adquire symbols names for the backtrace" << std::endl; 00084 #endif 00085 } 00086 00087 00088 // by default, CLAM asserts must breakpoint 00089 // we'll want to disable breakpoints for automatic assertion testing 00090 // purposes 00091 bool disabledCLAMAssertBreakpoint = false; 00092 00093 // Assert related 00094 00095 static void DefaultAssertHandler(const char* message, const char* filename, int lineNumber ) 00096 { 00097 std::cerr << "##########################################################" << std::endl; 00098 std::cerr << "################### ASSERTION FAILED #####################" << std::endl; 00099 std::cerr << "##########################################################" << std::endl; 00100 std::cerr << "At file " << filename << " line " << lineNumber << std::endl; 00101 std::cerr << message << std::endl; 00102 DumpBacktrace(std::cerr); 00103 } 00104 00105 static AssertFailedHandlerType CurrentAssertFailedHandler=DefaultAssertHandler; 00106 00107 AssertFailedHandlerType SetAssertFailedHandler(AssertFailedHandlerType handler) { 00108 AssertFailedHandlerType oldHandler = CurrentAssertFailedHandler; 00109 CurrentAssertFailedHandler = handler; 00110 return oldHandler; 00111 } 00112 00113 void ExecuteAssertFailedHandler(const char* message, const char* filename, int lineNumber ) 00114 { 00115 CurrentAssertFailedHandler(message,filename,lineNumber); 00116 } 00117 00118 bool ErrAssertionFailed::breakpointInCLAMAssertEnabled = true; 00119 00120 ErrAssertionFailed::ErrAssertionFailed(const char* message, const char* filename, int lineNumber) 00121 : Err(message) 00122 { 00123 if (!breakpointInCLAMAssertEnabled) return; 00124 00125 CurrentAssertFailedHandler( message, filename, lineNumber ); 00126 } 00127 00128 // Warning related 00129 00130 static void DefaultWarningHandler(const char* message, const char* filename, int lineNumber ) 00131 { 00132 std::cerr << "####### WARNING: At file " << filename << " line " << lineNumber << std::endl; 00133 std::cerr << "\033[31m" << message << "\033[0m" << std::endl; 00134 } 00135 00136 static WarningHandlerType CurrentWarningHandler=DefaultWarningHandler; 00137 00138 WarningHandlerType SetWarningHandler(WarningHandlerType handler) { 00139 WarningHandlerType oldHandler = CurrentWarningHandler; 00140 CurrentWarningHandler = handler; 00141 return oldHandler; 00142 } 00143 00144 void ExecuteWarningHandler(const char* message, const char* filename, int lineNumber ) 00145 { 00146 CurrentWarningHandler(message,filename,lineNumber); 00147 } 00148 00149 #if 0 // defined(__linux__) 00150 class SystemSignalTrapper 00151 { 00152 int _signal; 00153 sighandler_t _oldHandler; 00154 public: 00155 SystemSignalTrapper(int signal, sighandler_t handler) : 00156 _signal(signal) 00157 { 00158 _oldHandler = std::signal(signal, handler); 00159 } 00160 ~SystemSignalTrapper() 00161 { 00162 std::signal(_signal, _oldHandler); 00163 } 00164 }; 00165 void segvSignalHandler(int myInt) 00166 { 00167 std::cerr << std::endl; 00168 std::cerr << "##########################################################" << std::endl; 00169 std::cerr << "#################### BAD MEMORY ACCES ####################" << std::endl; 00170 std::cerr << "##########################################################" << std::endl; 00171 DumpBacktrace(std::cerr); 00172 std::abort(); 00173 } 00174 00175 static SystemSignalTrapper segvSignalTrapper(SIGSEGV,segvSignalHandler); 00176 #endif //defined linux 00177 00178 00179 } 00180 00181
1.7.6.1