* ./hurricane/src/hurricane:

- New: Backtrace to print the stack when an exception is thrown.
    - New: In Error, support for Backtrack.
    - Change: In TextTranslator, provides a default HTML translator instead of
        building it every time it was needed.
    - Bug: In Common, when demangling a C++ symbol fails, returns the empty
        string instead of NULL.

  * ./hurricane/src/viewer:
    - New: In Exception, support for the Backtrack new feature.

  * ./hurricane/src/isobar:
    - Change: In PyHurricane, when catching a C++ exception, adds a newline to
        have a more clean display.
This commit is contained in:
Jean-Paul Chaput 2010-11-16 13:43:34 +00:00
parent a9d0783026
commit 8be83b1ae0
15 changed files with 345 additions and 94 deletions

View File

@ -0,0 +1,120 @@
// -*- C++ -*-
//
// Copyright (c) BULL S.A. 2000-2010, All Rights Reserved
//
// This file is part of Hurricane.
//
// Hurricane is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Hurricane is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-
// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU
// General Public License for more details.
//
// You should have received a copy of the Lesser GNU General Public
// License along with Hurricane. If not, see
// <http://www.gnu.org/licenses/>.
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | H U R R I C A N E |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Remy Escassut |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./Error.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <execinfo.h>
#include <sstream>
#include <iomanip>
#include <boost/regex.hpp>
#include "hurricane/Backtrace.h"
namespace Hurricane {
using std::string;
using std::vector;
using std::setw;
using std::setfill;
using std::ostringstream;
// -------------------------------------------------------------------
// Class : "Hurricane::Backtrace".
TextTranslator Backtrace::_textTranslator = TextTranslator::toTextTranslator();
const size_t Backtrace::_stackSize = 50;
// Examples of stack symbol string:
// * Linux:
// nwidget(_ZN18SchematicException4initEb+0x47) [0x4515e1]
// * OSX:
// 3 libstdc++.6.dylib 0x9142514b _ZSt9terminatev + 29
Backtrace::Backtrace ()
: _stack()
{
void* rawStack [ _stackSize ];
size_t depth = backtrace ( rawStack, _stackSize );
char** symbols = backtrace_symbols ( rawStack, depth );
#ifdef __linux__
boost::regex re ( "([^/]+)\\(([^+]+)\\+" );
boost::cmatch match;
for ( size_t i=0 ; i<depth ; ++i ) {
if ( boost::regex_search(symbols[i],match,re) ) {
string function ( match[2].first, match[2].second );
string demangled ( demangle(function.c_str()) );
if ( demangled.empty() )
_stack.push_back ( (demangled.empty()) ? function : demangled );
else {
string reformated ( match[1].first, match[1].second );
reformated += "( <b>" + demangled + "</b> )";
_stack.push_back ( reformated );
}
} else {
_stack.push_back ( symbols[i] );
}
}
#else
# ifdef __APPLE__
boost::regex re ( "(\\d+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S)\\s+\\+\\s+(\\d+)" );
# else
_stack.push_back ( "Backtrace only supported under Linux & OSX." );
# endif
#endif
}
string Backtrace::htmlWhere () const
{
ostringstream where;
for ( size_t depth=0 ; depth<_stack.size() ; ++depth )
where << "<tt>[" << setw(2) << setfill('0') << depth << "] " << _stack[depth] << "</tt><br>";
return where.str();
}
} // End of Hurricane namespace.

View File

@ -2,6 +2,7 @@
include_directories ( ${HURRICANE_SOURCE_DIR}/src/hurricane )
set ( includes hurricane/Mask.h
hurricane/DebugSession.h
hurricane/Backtrace.h
hurricane/BasicLayer.h hurricane/BasicLayers.h
hurricane/RegularLayer.h hurricane/RegularLayers.h
hurricane/ViaLayer.h hurricane/ViaLayers.h
@ -86,6 +87,7 @@
set ( cpps Record.cpp
Slot.cpp
Commons.cpp
Backtrace.cpp
Exception.cpp
Bug.cpp
Error.cpp
@ -152,6 +154,6 @@
TextTranslator.cpp
)
add_library ( hurricane ${cpps} )
add_library ( hurricane ${cpps} ${Boost_LIBRARIES} )
install ( TARGETS hurricane DESTINATION lib${LIB_SUFFIX} )
install ( FILES ${includes} DESTINATION include/coriolis2/hurricane )

View File

@ -111,7 +111,8 @@ string demangle ( const char* symbol )
char demangled[length];
abi::__cxa_demangle ( symbol, demangled, &length, &status );
return demangled;
return (status == 0) ? demangled : "";
}
#else

View File

@ -38,9 +38,11 @@
// x-----------------------------------------------------------------x
# include <cstdarg>
# include "hurricane/Error.h"
#include <execinfo.h>
#include <cstdarg>
#include <iomanip>
#include <boost/regex.hpp>
#include "hurricane/Error.h"
namespace Hurricane {
@ -51,23 +53,26 @@ namespace Hurricane {
Error::Error ( const string& reason )
: Exception()
, _reason(reason)
, _code(0)
: Exception ()
, _reason (reason)
, _code (0)
, _backtrace()
{ }
Error::Error ( int code, const string& reason )
: Exception()
, _reason(reason)
, _code(code)
: Exception ()
, _reason (reason)
, _code (code)
, _backtrace()
{ }
Error::Error ( const char* format, ... )
: Exception()
, _reason()
, _code(0)
: Exception ()
, _reason ()
, _code (0)
, _backtrace()
{
static char formatted [ 8192 ];
va_list args;
@ -81,9 +86,10 @@ namespace Hurricane {
Error::Error ( int code, const char* format, ... )
: Exception()
, _reason()
, _code(code)
: Exception ()
, _reason ()
, _code (code)
, _backtrace()
{
static char formatted [ 8192 ];
va_list args;
@ -97,11 +103,11 @@ namespace Hurricane {
Error::Error ( const Error& error )
: Exception()
, _reason(error._reason)
, _code(error._code)
{
}
: Exception ()
, _reason (error._reason)
, _code (error._code)
, _backtrace(error._backtrace)
{ }
string Error::_getTypeName () const

View File

@ -20,41 +20,6 @@
#include "hurricane/Exception.h"
namespace {
using namespace Hurricane;
TextTranslator getDefaultTextTranslator ()
{
TextTranslator translator;
translator.addTranslation ( "<br>" , "\n" );
translator.addTranslation ( "<em>" , "" );
translator.addTranslation ( "</em>" , "" );
translator.addTranslation ( "<strong>" , "" );
translator.addTranslation ( "</strong>", "" );
translator.addTranslation ( "<tt>" , "" );
translator.addTranslation ( "</tt>" , "" );
translator.addTranslation ( "<b>" , "" );
translator.addTranslation ( "</b>" , "" );
translator.addTranslation ( "<i>" , "" );
translator.addTranslation ( "</i>" , "" );
translator.addTranslation ( "<big>" , "" );
translator.addTranslation ( "</big>" , "" );
translator.addTranslation ( "<small>" , "" );
translator.addTranslation ( "</small>" , "" );
translator.addTranslation ( "&lt;" , "<" );
translator.addTranslation ( "&gt;" , ">" );
return translator;
}
} // End of anonymous namespace.
namespace Hurricane {
@ -63,7 +28,7 @@ namespace Hurricane {
// Exception implementation
// ****************************************************************************************************
TextTranslator Exception::_textTranslator = getDefaultTextTranslator();
TextTranslator Exception::_textTranslator = TextTranslator::toTextTranslator();
TextTranslator Exception::_htmlTranslator;

View File

@ -33,6 +33,9 @@ namespace Hurricane {
using std::vector;
using std::cerr;
using std::endl;
TextTranslator TextTranslator::_toTextTranslator;
string TextTranslator::translate ( const string& source ) const
@ -61,4 +64,30 @@ namespace Hurricane {
}
const TextTranslator& TextTranslator::toTextTranslator ()
{
if ( _toTextTranslator._translations.empty() ) {
_toTextTranslator.addTranslation ( "<br>" , "\n" );
_toTextTranslator.addTranslation ( "<em>" , "" );
_toTextTranslator.addTranslation ( "</em>" , "" );
_toTextTranslator.addTranslation ( "<strong>" , "" );
_toTextTranslator.addTranslation ( "</strong>", "" );
_toTextTranslator.addTranslation ( "<tt>" , "" );
_toTextTranslator.addTranslation ( "</tt>" , "" );
_toTextTranslator.addTranslation ( "<b>" , "" );
_toTextTranslator.addTranslation ( "</b>" , "" );
_toTextTranslator.addTranslation ( "<i>" , "" );
_toTextTranslator.addTranslation ( "</i>" , "" );
_toTextTranslator.addTranslation ( "<big>" , "" );
_toTextTranslator.addTranslation ( "</big>" , "" );
_toTextTranslator.addTranslation ( "<small>" , "" );
_toTextTranslator.addTranslation ( "</small>" , "" );
_toTextTranslator.addTranslation ( "&lt;" , "<" );
_toTextTranslator.addTranslation ( "&gt;" , ">" );
}
return _toTextTranslator;
}
} // End of Hurricane namespace.

View File

@ -0,0 +1,77 @@
// -*- C++ -*-
//
// Copyright (c) BULL S.A. 2000-2009, All Rights Reserved
//
// This file is part of Hurricane.
//
// Hurricane is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// Hurricane is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-
// TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Lesser GNU
// General Public License for more details.
//
// You should have received a copy of the Lesser GNU General Public
// License along with Hurricane. If not, see
// <http://www.gnu.org/licenses/>.
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | H U R R I C A N E |
// | V L S I B a c k e n d D a t a - B a s e |
// | |
// | Author : Jean-Paul Chaput |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Header : "./hurricane/Backtrace.h" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#ifndef __HURRICANE_BACKTRACE__
#define __HURRICANE_BACKTRACE__
#include <string>
#include "hurricane/Commons.h"
#include "hurricane/TextTranslator.h"
namespace Hurricane {
class Backtrace {
public:
Backtrace ();
inline std::string where () const;
inline std::string textWhere () const;
std::string htmlWhere () const;
inline std::string _getTypeName () const;
inline std::string _getString () const;
private:
static TextTranslator _textTranslator;
static const size_t _stackSize;
std::vector<std::string> _stack;
};
// Inline Functions.
inline std::string Backtrace::where () const { return textWhere(); }
inline std::string Backtrace::textWhere () const { return _textTranslator.translate(htmlWhere()); }
inline std::string Backtrace::_getTypeName () const { return "Backtrace"; }
inline std::string Backtrace::_getString () const { return "<Backtrace>"; }
} // End of Hurricane namespace.
#endif

View File

@ -38,41 +38,43 @@
// x-----------------------------------------------------------------x
# ifndef __HURRICANE_ERROR__
# define __HURRICANE_ERROR__
#ifndef __HURRICANE_ERROR__
#define __HURRICANE_ERROR__
# include "hurricane/Exception.h"
#include "hurricane/Exception.h"
#include "hurricane/Backtrace.h"
namespace Hurricane {
class Error : public Exception {
public:
// Constructors.
Error ( const string& reason );
Error ( const char* format, ... );
Error ( int code, const string& reason );
Error ( int code, const char* format, ... );
Error ( const Error& error );
// Methods.
inline string getReason () const;
inline int getCode () const;
// Hurricane Managment.
virtual string _getTypeName () const;
virtual string _getString () const;
Error ( const string& reason );
Error ( const char* format, ... );
Error ( int code, const string& reason );
Error ( int code, const char* format, ... );
Error ( const Error& error );
inline string getReason () const;
inline int getCode () const;
inline string where () const;
inline string textWhere () const;
inline string htmlWhere () const;
virtual string _getTypeName () const;
virtual string _getString () const;
private:
// Internal: Attributes.
string _reason;
int _code;
string _reason;
int _code;
Backtrace _backtrace;
};
// Inline Functions.
inline string Error::getReason () const { return _reason; }
inline int Error::getCode () const { return _code; }
inline string Error::getReason () const { return _reason; }
inline int Error::getCode () const { return _code; }
inline string Error::where () const { return _backtrace.where(); }
inline string Error::textWhere () const { return _backtrace.textWhere(); }
inline string Error::htmlWhere () const { return _backtrace.htmlWhere(); }
} // End of Hurricane namespace.
@ -84,4 +86,4 @@ IOSTREAM_POINTER_SUPPORT(Hurricane::Error);
IOSTREAM_VALUE_SUPPORT(Hurricane::Error);
# endif // __HURRICANE_ERROR__
#endif // __HURRICANE_ERROR__

View File

@ -34,9 +34,10 @@ namespace Hurricane {
class TextTranslator {
public:
inline TextTranslator ();
inline void addTranslation ( const std::string& original, const std::string& translation );
std::string translate ( const std::string& source ) const;
static const TextTranslator& toTextTranslator ();
inline TextTranslator ();
inline void addTranslation ( const std::string& original, const std::string& translation );
std::string translate ( const std::string& source ) const;
private:
class Translation {
public:
@ -46,6 +47,7 @@ namespace Hurricane {
std::string _translation;
};
private:
static TextTranslator _toTextTranslator;
std::vector<Translation> _translations;
};

View File

@ -87,7 +87,7 @@
add_library ( isobar ${sources} )
target_link_libraries ( isobar hurricane ${PYTHON_LIBRARIES})
target_link_libraries ( isobar hurricane ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
add_library ( Hurricane MODULE ${sources} )
set_target_properties ( Hurricane PROPERTIES
COMPILE_FLAGS "${COMPILE_FLAGS} -D__PYTHON_MODULE__=1"

View File

@ -848,11 +848,13 @@ extern "C" {
# define HCATCH \
} \
catch ( Error& e ) { \
PyErr_SetString ( HurricaneError, getString(e).c_str() ); \
std::string message = "\n" + getString(e); \
PyErr_SetString ( HurricaneError, message.c_str() ); \
return ( NULL ); \
} \
catch ( Warning& w ) { \
PyErr_Warn ( HurricaneWarning, const_cast<char*>(getString(w).c_str()) ); \
std::string message = "\n" + getString(w); \
PyErr_Warn ( HurricaneWarning, const_cast<char*>(message.c_str()) ); \
}
} // End of extern "C".

View File

@ -26,6 +26,7 @@
#include <QCloseEvent>
#include <QLabel>
#include <QPushButton>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFrame>
@ -41,6 +42,7 @@ namespace Hurricane {
: QDialog (parent)
, _header (new QLabel())
, _message(new QLabel())
, _trace (new QLabel())
{
setAttribute ( Qt::WA_DeleteOnClose );
setModal ( true );
@ -54,6 +56,14 @@ namespace Hurricane {
_message->setTextFormat ( Qt::RichText );
_message->setText ( "<b>Oups! I did it again!</b>" );
_trace->setTextFormat ( Qt::RichText );
_trace->setText ( "<b>No program trace sets yet.</b>" );
_trace->hide ();
QCheckBox* showTrace = new QCheckBox ();
showTrace->setText ( "Show Program Trace" );
showTrace->setChecked ( false );
QLabel* ok = new QLabel ();
ok->setSizePolicy ( QSizePolicy::Preferred, QSizePolicy::MinimumExpanding );
ok->setPixmap ( QPixmap(":/images/gnome-core.png") );
@ -68,6 +78,10 @@ namespace Hurricane {
contButton->setSizePolicy ( QSizePolicy::Fixed, QSizePolicy::Fixed );
contButton->setText ( tr("Try to Continue") );
QFrame* separator = new QFrame ();
separator->setFrameShape ( QFrame::HLine );
separator->setFrameShadow ( QFrame::Sunken );
QHBoxLayout* hLayout2 = new QHBoxLayout ();
hLayout2->addStretch ( 1 );
hLayout2->addWidget ( contButton, Qt::AlignCenter );
@ -78,10 +92,13 @@ namespace Hurricane {
QVBoxLayout* vLayout1 = new QVBoxLayout ();
vLayout1->setContentsMargins ( 10, 10, 10, 10 );
vLayout1->setSpacing ( 0 );
vLayout1->addWidget ( _header , Qt::AlignCenter );
vLayout1->addWidget ( _message, Qt::AlignCenter );
vLayout1->addWidget ( _header , Qt::AlignCenter );
vLayout1->addWidget ( _message , Qt::AlignCenter );
vLayout1->addWidget ( separator );
vLayout1->addWidget ( showTrace , Qt::AlignLeft );
vLayout1->addWidget ( _trace , Qt::AlignCenter );
vLayout1->addSpacing ( 10 );
vLayout1->addLayout ( hLayout2, Qt::AlignCenter );
vLayout1->addLayout ( hLayout2 , Qt::AlignCenter );
QHBoxLayout* hLayout1 = new QHBoxLayout ();
hLayout1->setSizeConstraint ( QLayout::SetFixedSize );
@ -91,8 +108,9 @@ namespace Hurricane {
setLayout ( hLayout1 );
connect ( contButton , SIGNAL(clicked()), this, SLOT(accept()) );
connect ( abortButton, SIGNAL(clicked()), this, SLOT(reject()) );
connect ( contButton , SIGNAL(clicked()) , this, SLOT(accept()) );
connect ( abortButton, SIGNAL(clicked()) , this, SLOT(reject()) );
connect ( showTrace , SIGNAL(stateChanged(int)), this, SLOT(_showTrace(int)) );
}
@ -119,4 +137,17 @@ namespace Hurricane {
}
void ExceptionWidget::setTrace ( const QString& where )
{
_trace->setText ( where );
}
void ExceptionWidget::_showTrace ( int state )
{
if ( state == Qt::Checked ) _trace->show ();
else _trace->hide ();
}
} // End of Hurricane Namespace.

View File

@ -25,8 +25,9 @@
#include <csignal>
#include <iostream>
#include <iomanip>
#include "hurricane/Exception.h"
#include "hurricane/Error.h"
#include "hurricane/viewer/Graphics.h"
#include "hurricane/viewer/ExceptionWidget.h"
#include "hurricane/viewer/HApplication.h"
@ -37,6 +38,8 @@ namespace Hurricane {
using std::cerr;
using std::endl;
using std::setw;
using std::setfill;
using std::exception;
@ -76,6 +79,13 @@ namespace Hurricane {
try {
return QApplication::notify ( object, event );
}
catch ( Error& e ) {
ExceptionWidget* ew = new ExceptionWidget ();
ew->setMessage ( e.htmlWhat ().c_str() );
ew->setTrace ( e.htmlWhere().c_str() );
if ( ew->exec() == QDialog::Rejected )
kill ( getpid(), SIGSEGV );
}
catch ( Exception& e ) {
ExceptionWidget* ew = new ExceptionWidget ();
ew->setMessage ( e.htmlWhat().c_str() );

View File

@ -39,11 +39,15 @@ namespace Hurricane {
public:
ExceptionWidget ( QWidget* parent=NULL);
void setMessage ( const QString& );
void setTrace ( const QString& );
private:
QLabel* _header;
QLabel* _message;
QLabel* _trace;
protected:
virtual void closeEvent ( QCloseEvent* );
private slots:
void _showTrace ( int state );
};

View File

@ -1,4 +1,4 @@
include_directories ( ${HURRICANE_SOURCE_DIR}/src/hurricane )
add_executable ( htest HTest.cpp )
target_link_libraries ( htest hurricane )
target_link_libraries ( htest hurricane ${Boost_LIBRARIES} )