From: g0dil Date: Thu, 3 Apr 2008 09:18:18 +0000 (+0000) Subject: Socket/Protocols/INet: Allow socket address string representation to omit the address... X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=d2459b6c8249291588fd3d0d125ed3d38e003b55;p=senf.git Socket/Protocols/INet: Allow socket address string representation to omit the address/hostname Utils: Add WrapException template Utils/Daemon: BUGFIX: Only remove pidfile if we have created one ourselves git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@775 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Console/Node.cci b/Console/Node.cci index 5f824bd..c5adaf3 100644 --- a/Console/Node.cci +++ b/Console/Node.cci @@ -96,14 +96,20 @@ prefix_ senf::console::DirectoryNode & senf::console::DirectoryNode::operator[](std::string const & name) const { - return dynamic_cast(get(name)); + try { + return dynamic_cast(get(name)); + } + SENF_WRAP_EXC(std::bad_cast) } prefix_ senf::console::CommandNode & senf::console::DirectoryNode::operator()(std::string const & name) const { - return dynamic_cast(get(name)); + try { + return dynamic_cast(get(name)); + } + SENF_WRAP_EXC(std::bad_cast) } prefix_ senf::console::DirectoryNode & diff --git a/Packets/Packet.cti b/Packets/Packet.cti index b58b783..e16f88e 100644 --- a/Packets/Packet.cti +++ b/Packets/Packet.cti @@ -26,6 +26,7 @@ //#include "Packet.ih" // Custom includes +#include "../Utils/Exception.hh" #define prefix_ inline ///////////////////////////////cti.p/////////////////////////////////////// @@ -61,7 +62,7 @@ prefix_ OtherPacket senf::Packet::as() const { if (!is()) - throw std::bad_cast(); + throw WrapException(std::bad_cast()); return OtherPacket(ptr()->as()); } diff --git a/Socket/Protocols/INet/INetAddressing.cc b/Socket/Protocols/INet/INetAddressing.cc index d53ad07..6bc79e5 100644 --- a/Socket/Protocols/INet/INetAddressing.cc +++ b/Socket/Protocols/INet/INetAddressing.cc @@ -46,16 +46,16 @@ prefix_ senf::INet4SocketAddress::INet4SocketAddress(std::string const & addr) { clear(); - unsigned i = addr.find(':'); - if (i == std::string::npos) - throw AddressSyntaxException(); + unsigned portIx = addr.find(':'); try { - port(boost::lexical_cast< ::u_int16_t >(std::string(addr,i+1))); + port( boost::lexical_cast< ::u_int16_t >(portIx == std::string::npos + ? addr : std::string(addr,portIx+1)) ); } catch (boost::bad_lexical_cast const &) { - throw AddressSyntaxException(); + throw AddressSyntaxException() << "invalid port number"; } - address(INet4Address::from_string(std::string(addr,0,i))); + if (portIx != std::string::npos) + address( INet4Address::from_string(std::string(addr,0,portIx)) ); } prefix_ senf::INet4SocketAddress::INet4SocketAddress(INet4Address const & addr, unsigned p) @@ -81,8 +81,9 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr, // Format of addr: "[" address [ "%" interface ] "]" ":" port // or: host ":" port + // or: port - static boost::regex const addressRx ("(?:\\[([a-f0-9A-F:]+)(?:%(.+))?\\]|(.+)):([0-9]+)"); + static boost::regex const addressRx ("(?:(?:\\[([a-f0-9A-F:]+)(?:%(.+))?\\]|(.+)):)?([0-9]+)"); // Subexpression numbers: enum { NumericAddr = 1, ZoneId = 2, @@ -98,10 +99,12 @@ prefix_ senf::INet6SocketAddress::INet6SocketAddress(std::string const & addr, sockaddr_.sin6_port = htons(boost::lexical_cast(match[Port])); - INet6Address a (INet6Address::from_string( - match[NumericAddr].matched ? match[NumericAddr] : match[Hostname], - resolve)); - std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]); + if (match[NumericAddr].matched || match[Hostname].matched) { + INet6Address a (INet6Address::from_string( + match[NumericAddr].matched ? match[NumericAddr] : match[Hostname], + resolve)); + std::copy(a.begin(), a.end(), &sockaddr_.sin6_addr.s6_addr[0]); + } } prefix_ bool senf::INet6SocketAddress::operator==(INet6SocketAddress const & other) diff --git a/Socket/SocketHandle.cti b/Socket/SocketHandle.cti index 456a7b1..39b3273 100644 --- a/Socket/SocketHandle.cti +++ b/Socket/SocketHandle.cti @@ -113,7 +113,7 @@ senf::SocketHandle::cast_dynamic(FileHandle handle) { // throws bad_cast if the body is not a SocketBody SocketBody & body (dynamic_cast(FileHandle::body(handle))); - // throws bad_cast if the policy is not compatible + // throws bad_cast if the policy is not compatible (already wrapped ...) SPolicy::checkBaseOf(body.protocol().policy()); return cast_static(handle); } @@ -138,7 +138,10 @@ prefix_ Target senf::dynamic_socket_cast(Source handle) boost::is_convertible::value && ( boost::is_convertible::value || boost::is_convertible::value ) )); - return Target::cast_dynamic(handle); + try { + return Target::cast_dynamic(handle); + } + SENF_WRAP_EXC(std::bad_cast) } template diff --git a/Socket/SocketPolicy.ct b/Socket/SocketPolicy.ct index de3f111..fa9ca77 100644 --- a/Socket/SocketPolicy.ct +++ b/Socket/SocketPolicy.ct @@ -27,6 +27,7 @@ #include "SocketPolicy.ih" // Custom includes +#include "../Utils/Exception.hh" #define prefix_ ///////////////////////////////ct.p//////////////////////////////////////// @@ -46,7 +47,10 @@ checkBaseOf(SocketPolicyBase const & other) (void) dynamic_cast( \ other.BOOST_PP_CAT(the,SomePolicy)()); - BOOST_PP_SEQ_FOR_EACH( SP_CheckPolicy, , SENF_SOCKET_POLICIES ) + try { + BOOST_PP_SEQ_FOR_EACH( SP_CheckPolicy, , SENF_SOCKET_POLICIES ) + } + SENF_WRAP_EXC(std::bad_cast) # undef SP_CheckPolicy } diff --git a/Utils/Daemon/Daemon.cc b/Utils/Daemon/Daemon.cc index 13668ee..f1ac715 100644 --- a/Utils/Daemon/Daemon.cc +++ b/Utils/Daemon/Daemon.cc @@ -57,7 +57,7 @@ prefix_ senf::Daemon::~Daemon() { - if (! pidfile_.empty()) { + if (pidfileCreated_) { try { LIBC_CALL( ::unlink, (pidfile_.c_str()) ); } catch (Exception e) { @@ -77,11 +77,13 @@ prefix_ bool senf::Daemon::daemon() return daemonize_; } -prefix_ int senf::Daemon::argc() { +prefix_ int senf::Daemon::argc() +{ return argc_; } -prefix_ char const ** senf::Daemon::argv() { +prefix_ char const ** senf::Daemon::argv() +{ return argv_; } @@ -194,10 +196,14 @@ prefix_ int senf::Daemon::start(int argc, char const ** argv) openLog(); fork(); } - if (! pidfile_.empty() && ! pidfileCreate()) { - std::cerr << "\n*** PID file '" << pidfile_ << "' creation failed. Daemon running ?" - << std::endl; - return 1; + if (! pidfile_.empty()) { + if (pidfileCreate()) + pidfileCreated_ = true; + else { + std::cerr << "PID file '" << pidfile_ + << "' creation failed. Daemon running ?" << std::endl; + return 1; + } } main(); @@ -209,11 +215,11 @@ prefix_ int senf::Daemon::start(int argc, char const ** argv) #ifndef SENF_DEBUG catch (std::exception & e) { - std::cerr << "\n*** Fatal exception: " << e.what() << std::endl; + std::cerr << "\n*** Fatal exception: " << e.what() << "\n" << std::endl; return 1; } catch (...) { - std::cerr << "\n*** Fatal exception: (unknown)" << std::endl; + std::cerr << "\n*** Fatal exception: (unknown)" << "\n" << std::endl; return 1; } @@ -227,7 +233,7 @@ prefix_ int senf::Daemon::start(int argc, char const ** argv) prefix_ senf::Daemon::Daemon() : argc_(0), argv_(0), daemonize_(true), stdout_(-1), stderr_(-1), pidfile_(""), - detached_(false) + pidfileCreated_(false), detached_(false) {} //////////////////////////////////////// @@ -369,8 +375,10 @@ prefix_ bool senf::Daemon::pidfileCreate() if ( ! (pidf >> old_pid) || old_pid < 0 || ::kill(old_pid, 0) >= 0 - || errno == EPERM ) + || errno == EPERM ) { + LIBC_CALL( ::unlink, (tempname.c_str()) ); return false; + } } // If we reach this point, the pid file exists but the process mentioned within the diff --git a/Utils/Daemon/Daemon.hh b/Utils/Daemon/Daemon.hh index 30d6b24..2a0ee69 100644 --- a/Utils/Daemon/Daemon.hh +++ b/Utils/Daemon/Daemon.hh @@ -209,6 +209,7 @@ namespace senf { int stdout_; int stderr_; std::string pidfile_; + bool pidfileCreated_; bool detached_; }; diff --git a/Utils/Exception.cc b/Utils/Exception.cc index c86dade..4c74f6c 100644 --- a/Utils/Exception.cc +++ b/Utils/Exception.cc @@ -38,18 +38,8 @@ /////////////////////////////////////////////////////////////////////////// // senf::Exception -prefix_ senf::Exception::~Exception() - throw() -{} - -prefix_ char const * senf::Exception::what() - const throw() -{ - return message_.c_str(); -} - #ifdef SENF_DEBUG -prefix_ void senf::Exception::addBacktrace() +prefix_ void senf::ExceptionMixin::addBacktrace() { void * entries[SENF_DEBUG_BACKTRACE_NUMCALLERS]; unsigned nEntries( ::backtrace(entries, SENF_DEBUG_BACKTRACE_NUMCALLERS) ); @@ -80,6 +70,19 @@ prefix_ void senf::Exception::addBacktrace() } #endif +/////////////////////////////////////////////////////////////////////////// +// senf::Exception + +prefix_ senf::Exception::~Exception() + throw() +{} + +prefix_ char const * senf::Exception::what() + const throw() +{ + return message().c_str(); +} + /////////////////////////////////////////////////////////////////////////// // senf::SystemException diff --git a/Utils/Exception.cci b/Utils/Exception.cci index 1b611a2..189c2f1 100644 --- a/Utils/Exception.cci +++ b/Utils/Exception.cci @@ -28,9 +28,9 @@ ///////////////////////////////cci.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::Exception +// senf::ExceptionMixin -prefix_ senf::Exception::Exception(std::string const & description) +prefix_ senf::ExceptionMixin::ExceptionMixin(std::string const & description) : message_(description) { #ifdef SENF_DEBUG @@ -38,18 +38,25 @@ prefix_ senf::Exception::Exception(std::string const & description) #endif } -prefix_ std::string const & senf::Exception::message() +prefix_ std::string const & senf::ExceptionMixin::message() const { return message_; } -prefix_ void senf::Exception::append(std::string text) +prefix_ void senf::ExceptionMixin::append(std::string text) { message_ += text; } /////////////////////////////////////////////////////////////////////////// +// senf::Exception + +prefix_ senf::Exception::Exception(std::string const & description) + : ExceptionMixin(description) +{} + +/////////////////////////////////////////////////////////////////////////// // senf::SystemException prefix_ senf::SystemException::SystemException(std::string const & descr _SENF_EXC_DEBUG_ARGS_ND) diff --git a/Utils/Exception.cti b/Utils/Exception.cti index a398908..ea12370 100644 --- a/Utils/Exception.cti +++ b/Utils/Exception.cti @@ -32,13 +32,33 @@ ///////////////////////////////cti.p/////////////////////////////////////// template -prefix_ typename boost::enable_if< boost::is_convertible, Exc & >::type +prefix_ typename boost::enable_if< boost::is_convertible, Exc & >::type senf::operator<<(Exc const & exc, Arg const & arg) { const_cast(exc).append( boost::lexical_cast(arg) ); return const_cast(exc); } +/////////////////////////////////////////////////////////////////////////// +// senf::WrapExcecption + +template +prefix_ senf::WrapException::WrapException(BaseException const & base) + : ExceptionMixin(base.what()), BaseException(base) +{} + +template +prefix_ senf::WrapException::~WrapException() + throw() +{} + +template +prefix_ char const * senf::WrapException::what() + const throw() +{ + return message().c_str(); +} + /////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/Utils/Exception.hh b/Utils/Exception.hh index fefe136..840379e 100644 --- a/Utils/Exception.hh +++ b/Utils/Exception.hh @@ -42,7 +42,8 @@ /** \defgroup exception Exception classes All exceptions in %senf are derived from senf::Exception. This class adds the possibility to - extend the exception description while it is processed: + extend the exception description while it is processed. The functionality is provided by a mixin + class senf::ExceptionMixin: \code try { @@ -50,7 +51,7 @@ // Some code which might raise an arbitrary senf exception } - catch (senf::Exception & e) { + catch (senf::ExceptionMixin & e) { e << "\handling user " << user; throw; } @@ -64,7 +65,7 @@ try { // ... } - catch (senf::Exception & e) { + catch (senf::ExceptionMixin & e) { e << boost::format("\ncall id 0x%04x@%s") % id % address; } \endcode @@ -84,38 +85,63 @@ automatically include a stack backtrace. For this to work, you need to add the -rdynamic option to all link commands. This feature depends on gcc and the GNU-libc. + + To apply these features (extensibility, backtrace) to a non-senf exception, the non-senf + exception can be wrapped and rethrown. + \code + void foo() { + try { + // ... code that might throw std::bad_cast or somelib::FooException + } + SENF_WRAP_EXC(std::bad_cast) + SENF_WRAP_EXC(somelib::FooException) + } + \endcode The re-thrown exception can then be caught as std::bad_cast or as + senf::ExceptionMixin as needed. It is safe, to wrap an exception twice (the macro will detect + this case). + \code + bar() { + try { + try { + foo(); + } + catch (senf::ExceptionMixin & ex) { + ex << "\nadd this info"; + } + } + catch (std::bad_cast const & ex) { + std::cerr << ex.what() << std::endl; + } + \endcode + The final error output will include + \li a backtrace if compiled in debug mode + \li the original error message from the std::bad_cast exception + \li the additional error message "add this info" + + \todo Link against libcwd to add file-name/line-number information to the backtrace and remove + the dependency on -rdynamic */ namespace senf { - /** \brief Generic exception base-class + /** \brief Generic extensible exception mixin - Exception is a generic exception base-class which allows the exception to be later extended + ExceptionMixin is a generic exception mixin which allows the exception to be later extended by catching and re-throwing it (See example in \ref exception). \ingroup exception */ - class Exception - : public std::exception + class ExceptionMixin { public: - /////////////////////////////////////////////////////////////////////////// - ///\name Structors and default members - ///@{ - - virtual ~Exception() throw(); - - ///@} - /////////////////////////////////////////////////////////////////////////// - - virtual char const * what() const throw(); std::string const & message() const; void append(std::string text); ///< Extend exception description /**< Adds \a text to the description text. */ protected: - Exception(std::string const & description = ""); ///< Initialize exception with string + explicit ExceptionMixin(std::string const & description = ""); + ///< Initialize exception with string /**< \a description is the initial error description string. This should probably be a string constant describing the exception for most derived @@ -128,8 +154,65 @@ namespace senf { std::string message_; }; + /** \brief Extensible exception base-class + + This base-class is an exception which already includes the ExceptionMixin. All SENF + exceptions are derived from this class. Other user-exception may be defined by deriving from + this class too. + + \see \ref exception + + \ingroup exception + */ + class Exception + : public ExceptionMixin, public std::exception + { + public: + virtual ~Exception() throw(); + + virtual char const * what() const throw(); + + protected: + explicit Exception(std::string const & description = ""); + }; + + /** \brief Wrapper for standard non-senf exceptions + + This class wraps an exception of type \a BaseException and adds functionality from + senf::ExceptionMixin. + + \ingroup exception + */ + template + class WrapException + : public ExceptionMixin, public BaseException + { + public: + typedef BaseException Base; + + WrapException(BaseException const & base); + virtual ~WrapException() throw(); + + virtual char const * what() const throw(); + }; + + /** \brief Wrap a non-senf exception + + This macro allows to wrap a non-senf exception adding functionality from ExceptionMixin + using the WrapException template. For an example, see \ref exception. + + \ingroup exception + */ +# define SENF_WRAP_EXC(Ex) \ + catch (Ex const & base) { \ + if (dynamic_cast(&base)) \ + throw; \ + else \ + throw senf::WrapException(base); \ + } + template - typename boost::enable_if< boost::is_convertible, Exc & >::type + typename boost::enable_if< boost::is_convertible, Exc & >::type operator<<(Exc const & exc, Arg const & arg); ///< Extend exception description /**< Adds \a arg converted to string to the end of the exception description string. This operator allows to diff --git a/Utils/Exception.test.cc b/Utils/Exception.test.cc index 9a29f71..7706bcd 100644 --- a/Utils/Exception.test.cc +++ b/Utils/Exception.test.cc @@ -37,6 +37,38 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// +BOOST_AUTO_UNIT_TEST(wrapException) +{ + bool bad_cast (false); + + try { + try { + try { + try { + try { + throw std::bad_cast(); + } + SENF_WRAP_EXC(std::bad_cast) + } + SENF_WRAP_EXC(std::bad_cast) + } + catch (senf::ExceptionMixin & ex) { + ex << "\nspecial exception"; + throw; + } + } + catch (std::exception const & ex) { + BOOST_CHECK( std::string(ex.what()).find("-- \n") != std::string::npos ); + BOOST_CHECK( std::string(ex.what()).find("special exception") != std::string::npos ); + throw; + } + } + catch (std::bad_cast &) { + bad_cast = true; + } + BOOST_CHECK( bad_cast ); +} + BOOST_AUTO_UNIT_TEST(errnoException) { try {