Commit 25307b53 authored by Eric Cano's avatar Eric Cano
Browse files

Re-instated inheritance from std::exception for castor::exception::Exception.

Added an std::exception::Backtrace class, providing a backtrace attached to all exception.
Fixed minor side effects (virtual destructors, catch orders) induced by the inheritance from std::exception.
parent 6d73cd65
/******************************************************************************
* Backtrace.cpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
*
* @author Eric Cano
*****************************************************************************/
#include <execinfo.h>
#include <cxxabi.h>
#include <stdlib.h>
#include "Backtrace.hpp"
castor::exception::Backtrace::Backtrace(): m_trace() {
void * array[200];
size_t depth = ::backtrace(array, sizeof(array)/sizeof(void*));
char ** strings = ::backtrace_symbols(array, depth);
if (!strings)
m_trace = "";
else {
for (size_t i=0; i<depth; i++) {
std::string line(strings[i]);
/* Demangle the c++, if possible. We expect the c++ function name's to live
* between a '(' and a +
* line format: /usr/lib/somelib.so.1(_Mangle2Mangle3Ev+0x123) [0x12345] */
if ((std::string::npos != line.find("(")) && (std::string::npos != line.find("+"))) {
std::string before, theFunc, after;
before = line.substr(0, line.find("(")+1);
theFunc = line.substr(line.find("(")+1, line.find("+") - (line.find("(") + 1));
after = line.substr(line.find("+"), std::string::npos);
int status(-1);
char demangled[200];
size_t length(sizeof(demangled));
abi::__cxa_demangle(theFunc.c_str(), demangled, &length, &status);
if (0 == status) {
m_trace += before;
m_trace += demangled;
m_trace += after;
m_trace += "(C++ demangled)\n";
} else {
m_trace += strings[i];
m_trace += "\n";
}
} else {
m_trace += strings[i];
m_trace += "\n";
}
}
free (strings);
}
}
\ No newline at end of file
/******************************************************************************
* Backtrace.hpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
*
* @author Eric Cano
*****************************************************************************/
#pragma once
#include <string>
namespace castor {
namespace exception {
class Backtrace {
public:
Backtrace();
operator std::string() const { return m_trace; }
private:
std::string m_trace;
};
}
}
\ No newline at end of file
......@@ -46,6 +46,12 @@ namespace castor {
*/
Communication(std::string requestId,
int errorCode);
/**
* Empty Destructor, explicitely non-throwing (needed for std::exception
* inheritance)
*/
virtual ~Communication() throw () {}
std::string getRequestId();
......
......@@ -49,7 +49,17 @@ castor::exception::Exception& castor::exception::Exception::operator=(castor::ex
return *this;
}
//------------------------------------------------------------------------------
// what operator
//------------------------------------------------------------------------------
const char * castor::exception::Exception::what() {
m_what = getMessage().str();
m_what += "\n";
m_what += (std::string) m_backtrace;
return m_what.c_str();
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
castor::exception::Exception::~Exception() {}
castor::exception::Exception::~Exception() throw() {}
......@@ -27,8 +27,10 @@
#define EXCEPTION_EXCEPTION_HPP 1
// Include Files
#include "castor/exception/Backtrace.hpp"
#include <serrno.h>
#include <sstream>
#include <exception>
namespace castor {
......@@ -38,7 +40,7 @@ namespace castor {
* class Exception
* A simple exception used for error handling in castor
*/
class Exception {
class Exception: public std::exception {
public:
......@@ -59,9 +61,10 @@ namespace castor {
Exception& operator=(Exception &dbex);
/**
* Empty Destructor
* Empty Destructor, explicitely non-throwing (needed for std::exception
* inheritance)
*/
virtual ~Exception();
virtual ~Exception() throw ();
/**
* Get the value of m_message
......@@ -71,6 +74,21 @@ namespace castor {
std::ostringstream& getMessage() {
return m_message;
}
/**
* Get the backtrace's contents
* @return backtrace in a standard string.
*/
std::string const backtrace() {
return (std::string)m_backtrace;
}
/**
* Updates the m_what member with a concatenation of the message and
* the stack trace.
* @return pointer to m_what's contents
*/
virtual const char * what();
/**
* gets the serrno code of the corresponding C error
......@@ -85,6 +103,18 @@ namespace castor {
* The serrno code of the corresponding C error
*/
int m_serrno;
/**
* Placeholder for the what result. It has to be a member
* of the object, and not on the stack of the "what" function.
*/
std::string m_what;
/**
* Backtrace object. Its constructor does the heavy lifting of
* generating the backtrace.
*/
Backtrace m_backtrace;
};
......
......@@ -49,6 +49,12 @@ namespace castor { namespace exception {
InvalidConfigEntry(const char *const category,
const char *const entryName, const char *const entryValue);
/**
* Trivial, but explicitely non-throwing destructor (required through
* inheritence from std::exception)
*/
virtual ~InvalidConfigEntry() throw () {};
/**
* Returns the category of the configuration entry.
*/
......
......@@ -32,7 +32,7 @@
castor::exception::NoPortInRange::NoPortInRange(
const unsigned short lowPort,
const unsigned short highPort) throw() :
exception::Exception(SENOPORTINRANGE),
castor::exception::Exception(SENOPORTINRANGE),
m_lowPort(lowPort),
m_highPort(highPort) {
......
......@@ -48,7 +48,13 @@ public:
*/
NoPortInRange(const unsigned short lowPort, const unsigned short highPort)
throw();
/**
* Empty Destructor, explicitely non-throwing (needed for std::exception
* inheritance)
*/
virtual ~NoPortInRange() throw () {}
/**
* Returns the inclusive low port of the port number range.
*/
......
......@@ -1237,14 +1237,13 @@ void castor::tape::tapebridge::BridgeProtocolEngine::endRtcpdSession() throw() {
": Unknown VolumeMode"
": Actual=" << m_volume.mode());
}
} catch(castor::exception::Exception &ex) {
// Simply rethrow as there is no need to convert exception type
throw ex;
} catch(std::exception &se) {
TAPE_THROW_EX(castor::exception::Internal,
": Caught a std::exception"
": what=" << se.what());
} catch(castor::exception::Exception &ex) {
// Simply rethrow as there is no need to convert exception type
throw ex;
} catch(...) {
TAPE_THROW_EX(castor::exception::Internal,
": Caught an unknown exception");
......@@ -3510,13 +3509,15 @@ void castor::tape::tapebridge::BridgeProtocolEngine::
": Actual=" << m_volume.mode());
}
}
} catch(castor::exception::Exception &ex) {
// Simply rethrow as there is no need to convert exception type
// this is safe, as the next catch block will not intercept this
// also-std::exception-exception
throw ex;
} catch(std::exception &se) {
TAPE_THROW_EX(castor::exception::Internal,
": Caught a std::exception"
": what=" << se.what());
} catch(castor::exception::Exception &ex) {
// Simply rethrow as there is no need to convert exception type
throw ex;
} catch(...) {
TAPE_THROW_EX(castor::exception::Internal,
": Caught an unknown exception");
......@@ -3722,13 +3723,13 @@ void castor::tape::tapebridge::BridgeProtocolEngine::notifyClientEndOfSession()
m_tapebridgeTransactionCounter.next();
m_clientProxy.notifyEndOfSession(tapebridgeTransId);
}
} catch(castor::exception::Exception &ex) {
// Add some context information and rethrow exception
TAPE_THROW_CODE(ex.code(), ": " << ex.getMessage().str());
} catch(std::exception &se) {
TAPE_THROW_EX(castor::exception::Internal,
": Caught a std::exception"
": what=" << se.what());
} catch(castor::exception::Exception &ex) {
// Add some context information and rethrow exception
TAPE_THROW_CODE(ex.code(), ": " << ex.getMessage().str());
} catch(...) {
TAPE_THROW_EX(castor::exception::Internal,
": Caught an unknown exception");
......
......@@ -30,7 +30,7 @@
//-----------------------------------------------------------------------------
castor::tape::tapebridge::SessionException::SessionException(
const SessionError &sessionError) throw() :
exception::Exception(ETSESSIONERROR),
castor::exception::Exception(ETSESSIONERROR),
m_sessionError(sessionError) {
// Do nothing
}
......
......@@ -53,6 +53,12 @@ public:
*/
SessionException(const SessionError &sessionError) throw();
/**
* Empty Destructor, explicitely non-throwing (needed for std::exception
* inheritance)
*/
virtual ~SessionException() throw () {}
/**
* Returns a "read only" (const) reference to the wrapped SessionError
* object.
......
......@@ -33,6 +33,7 @@ set (COMMON_LIB_SRC_FILES
socket_timeout.c u64subr.c Cinitdaemon.c Cgetopt.c
Cregexp.c Cexportconf.c Csnprintf.c util.c
Csecloader.c castor1compat.c
../castor/exception/Backtrace.cpp
../castor/exception/BadVersion.cpp
../castor/exception/Busy.cpp
../castor/exception/DismountFailed.cpp
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment