Assert.cxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3