diff --git a/Socket/FileHandle.cc b/Socket/FileHandle.cc index 28724697018470ec74937bb02a1b08d6df8d7224..4ce3835e2f8056008a1dce6382a0014fcf54cb26 100644 --- a/Socket/FileHandle.cc +++ b/Socket/FileHandle.cc @@ -38,6 +38,36 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// senf::FileBody + +prefix_ void senf::FileBody::close() +{ + if (!valid()) + throwErrno(EBADF); + v_close(); + fd_ = -1; +} + +prefix_ void senf::FileBody::terminate() +{ + if (valid()) { + v_terminate(); + fd_ = -1; + } +} + +prefix_ void senf::FileBody::destroyClose() +{ + if (valid()) + try { + close(); + } + catch (...) { + terminate(); + } +} + prefix_ void senf::FileBody::v_close() { if (::close(fd_) != 0) diff --git a/Socket/FileHandle.cci b/Socket/FileHandle.cci index 9f82d08a3be780287ce05c523dfaf22cf0eaebfa..79308aee6ee4ff85d688a4ef95ad98eb36c87393 100644 --- a/Socket/FileHandle.cci +++ b/Socket/FileHandle.cci @@ -41,33 +41,6 @@ prefix_ senf::FileBody::FileBody(int fd) : fd_(fd) {} -prefix_ senf::FileBody::~FileBody() -{ - if (valid()) - try { - close(); - } - catch (...) { - terminate(); - } -} - -prefix_ void senf::FileBody::close() -{ - if (!valid()) - throwErrno(EBADF); - v_close(); - fd_ = -1; -} - -prefix_ void senf::FileBody::terminate() -{ - if (valid()) { - v_terminate(); - fd_ = -1; - } -} - prefix_ senf::FileHandle senf::FileBody::handle() { return FileHandle(ptr(this)); @@ -196,6 +169,12 @@ prefix_ senf::FileHandle::FileHandle() : body_(0) {} +prefix_ senf::FileHandle::~FileHandle() +{ + if (body_ && ! body().is_shared()) + body().destroyClose(); +} + prefix_ senf::FileHandle::FileHandle(std::auto_ptr<FileBody> body) : body_(body.release()) {} diff --git a/Socket/FileHandle.hh b/Socket/FileHandle.hh index 2ae609af89d770962312fd3e8d366ac734213e86..5b0e34db74cb449611fa9a2207078d75bff35de9 100644 --- a/Socket/FileHandle.hh +++ b/Socket/FileHandle.hh @@ -123,6 +123,7 @@ namespace senf { ///@{ FileHandle(); + ~FileHandle(); // my default constructor // default copy constructor diff --git a/Socket/FileHandle.ih b/Socket/FileHandle.ih index cdc775debde9ff512edad6add84ad132f6ee781e..e87e3192b829a8ea618dd5b858df95d0ebe1ce5a 100644 --- a/Socket/FileHandle.ih +++ b/Socket/FileHandle.ih @@ -83,7 +83,10 @@ namespace senf { constructor not some arbitrary id even if you overload all the virtual members. If the file descriptor is -1 the resulting body/handle is not valid() */ - virtual ~FileBody(); + + // NO DESTRUCTOR HERE - destructors and virtual functions don't mix. What would be in the + // the destructor is in 'destroyClose()' which is called from FileHandle::~FileHandle() + // *before* the last handle dies. // no copy // no conversion constructors @@ -98,6 +101,7 @@ namespace senf { void close(); void terminate(); + void destroyClose(); bool readable() const; void waitReadable() const; diff --git a/Socket/SocketHandle.cc b/Socket/SocketHandle.cc index 14fd6b275cb970db8fc52e564aa7b5798d133101..aa0cf61fef20b4dc9d9380cb2f993492516aa751 100644 --- a/Socket/SocketHandle.cc +++ b/Socket/SocketHandle.cc @@ -36,6 +36,19 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +// senf::SocketBody + +prefix_ void senf::SocketBody::state(SocketStateMap & map, unsigned lod) +{ + map["file.handle"] << fd(); + map["file.refcount"] << refcount(); + map["socket.server"] << isServer(); + map["socket.protocol"] << v_protocolName(); + map["socket.protocol.policy"] << prettyName(typeid(protocol().policy())); + protocol().state(map,lod); +} + prefix_ void senf::SocketBody::v_close() { protocol().close(); @@ -52,16 +65,6 @@ prefix_ bool senf::SocketBody::v_eof() return protocol().eof(); } -prefix_ void senf::SocketBody::state(SocketStateMap & map, unsigned lod) -{ - map["file.handle"] << fd(); - map["file.refcount"] << refcount(); - map["socket.server"] << isServer(); - map["socket.protocol"] << v_protocolName(); - map["socket.protocol.policy"] << prettyName(typeid(protocol().policy())); - protocol().state(map,lod); -} - /////////////////////////////////////////////////////////////////////////// // senf::detail::StateMapOrdering diff --git a/Socket/SocketHandle.test.cc b/Socket/SocketHandle.test.cc index e377f0bc4dce28eced4c149cc7b01e735741dfcc..709fb9ff38c13e0088d9acd597bb6c415a8b25b3 100644 --- a/Socket/SocketHandle.test.cc +++ b/Socket/SocketHandle.test.cc @@ -45,7 +45,7 @@ namespace { MySocketHandle() : senf::SocketHandle<senf::test::SomeProtocol::Policy>( std::auto_ptr<senf::SocketBody>( - new senf::ProtocolSocketBody<senf::test::SomeProtocol>(false))) + new senf::ProtocolSocketBody<senf::test::SomeProtocol>(false, 0))) {} }; @@ -66,33 +66,38 @@ BOOST_AUTO_UNIT_TEST(socketHandle) >::policy OtherSocketPolicy; typedef senf::SocketHandle<OtherSocketPolicy> OtherSocketHandle; - MySocketHandle myh; - OtherSocketHandle osh (myh); - osh = myh; - - typedef senf::SocketHandle<senf::test::SomeProtocol::Policy> SomeSocketHandle; - SomeSocketHandle ssh = senf::static_socket_cast<SomeSocketHandle>(osh); - - BOOST_CHECK_NO_THROW( senf::dynamic_socket_cast<SomeSocketHandle>(osh) ); - - typedef senf::SocketHandle< senf::MakeSocketPolicy< - OtherSocketPolicy, - senf::NoAddressingPolicy - >::policy> SomeOtherSocketHandle; - - BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeOtherSocketHandle>(osh), - std::bad_cast ); - BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeSocketHandle>( - senf::FileHandle(FDHandle())), - std::bad_cast ); - - BOOST_CHECK_EQUAL( myh.dumpState(), - "file.handle: -1\n" - "file.refcount: 3\n" - "handle: senf::SocketHandle<senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy> >\n" - "socket.protocol: senf::test::SomeProtocol\n" - "socket.protocol.policy: senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy>\n" - "socket.server: false\n" ); + { + MySocketHandle myh; + OtherSocketHandle osh (myh); + osh = myh; + + typedef senf::SocketHandle<senf::test::SomeProtocol::Policy> SomeSocketHandle; + SomeSocketHandle ssh = senf::static_socket_cast<SomeSocketHandle>(osh); + + BOOST_CHECK_NO_THROW( senf::dynamic_socket_cast<SomeSocketHandle>(osh) ); + + typedef senf::SocketHandle< senf::MakeSocketPolicy< + OtherSocketPolicy, + senf::NoAddressingPolicy + >::policy> SomeOtherSocketHandle; + + BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeOtherSocketHandle>(osh), + std::bad_cast ); + BOOST_CHECK_THROW( senf::dynamic_socket_cast<SomeSocketHandle>( + senf::FileHandle(FDHandle())), + std::bad_cast ); + + BOOST_CHECK_EQUAL( myh.dumpState(), + "file.handle: 0\n" + "file.refcount: 3\n" + "handle: senf::SocketHandle<senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy> >\n" + "socket.protocol: senf::test::SomeProtocol\n" + "socket.protocol.policy: senf::SocketPolicy<senf::test::SomeAddressingPolicy, senf::test::SomeFramingPolicy, senf::test::SomeCommunicationPolicy, senf::test::SomeReadPolicy, senf::test::SomeWritePolicy>\n" + "socket.server: false\n" ); + } + + // Ensure, the destructor is called and calls the correct close() implementation + BOOST_CHECK_EQUAL( senf::test::SomeProtocol::closeCount(), 1u ); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Socket/SocketProtocol.cc b/Socket/SocketProtocol.cc index e252603c14f15e47ea76323d905121b8117396f9..ca2866436d3ecf5ecf4924444dec24b721ea32aa 100644 --- a/Socket/SocketProtocol.cc +++ b/Socket/SocketProtocol.cc @@ -33,6 +33,7 @@ //#include "SocketProtocol.mpp" #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// + prefix_ void senf::SocketProtocol::close() const { diff --git a/Socket/SocketProtocol.hh b/Socket/SocketProtocol.hh index db71a83e8fbe4314a6bddaeaba2c1464db3c48e4..72ddad5479771de469c84618d8a25299f3f86956 100644 --- a/Socket/SocketProtocol.hh +++ b/Socket/SocketProtocol.hh @@ -174,7 +174,8 @@ namespace senf { virtual void close() const; ///< Close socket /**< This override will automatically \c shutdown() the socket whenever it is closed. - \throws senf::SystemException */ + \throws senf::SystemException + \fixme Move into (at least) BSDSOcketProtocol */ virtual void terminate() const; ///< Forcibly close socket /**< This override will automatically \c shutdown() the @@ -182,7 +183,8 @@ namespace senf { disable SO_LINGER to ensure, that v_terminate will not block. Like the overriden method, this member will ignore failures and will never throw. It is therefore safe to be - called from a destructor. */ + called from a destructor. + \fixme Move into (at least) BSDSocketProtocol */ virtual void state(SocketStateMap & map, unsigned lod) const; ///< Return socket state information diff --git a/Socket/SocketProtocol.test.hh b/Socket/SocketProtocol.test.hh index 3ca682abf7c8a8b1a25ffa1e096846e61789bcdc..c5073f3971b21a58a0686be75768ce09f4118cd6 100644 --- a/Socket/SocketProtocol.test.hh +++ b/Socket/SocketProtocol.test.hh @@ -27,6 +27,7 @@ #include "SocketProtocol.hh" #include "SocketPolicy.test.hh" #include "ProtocolClientSocketHandle.hh" +#include "../Utils/Logger/SenfLog.hh" //#include "SocketProtocol.test.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -40,13 +41,24 @@ namespace test { public: ~SomeProtocol() {} - void init_client() const {} - void init_server() const {} + void init_client() const { fd(0); } + void init_server() const { fd(0); } unsigned available() const { return Policy::ReadPolicy::TEST_SIZE; } bool eof() const { return false; } + + virtual void close() const { + SENF_LOG(( "Closing socket ..." )); + closeCount(1); + } + + static unsigned closeCount(unsigned inc=0) { + static unsigned counter (0); + counter += inc; + return counter; + } }; }} diff --git a/debian/rules b/debian/rules index 911d1b80dd24595f5cca79beb8d56b5e7f315721..b87c105a7427ae671c3629dd291f35d321bdfff2 100755 --- a/debian/rules +++ b/debian/rules @@ -76,7 +76,7 @@ build-indep-stamp: configure-stamp scons all_docs scons linklint scons fixlinks - scons $(destdir)/usr/include $(destdir)/usr/share/doc $(SCONS_OPTIONS) \ + scons $(destdir)/usr/include $(destdir)/usr/share/doc \ PREFIX='$(destdir)/usr' \ DOCINSTALLDIR='$$PREFIX/share/doc/libsenf-doc/html' \ INCLUDEINSTALLDIR='$$PREFIX/include/senf' diff --git a/doclib/SConscript b/doclib/SConscript index 102709e08caf561de97d5a13f1a6412e36fe78ce..276ec2d6555dafbeecc6fbdfd6ff9c1c5f5df814 100644 --- a/doclib/SConscript +++ b/doclib/SConscript @@ -29,8 +29,9 @@ # 1. Scanning the Doxyfile's # # The doxygen builder scans all documentation source files which have -# the text 'doxyfile' in any case within them. It understands @INCLUDE -# directives and will find all the dependencies of the documentation: +# the text 'doxyfile' in any case in their name. It understands +# @INCLUDE directives and will find all the dependencies of the +# documentation: # # * All the source files as selected by INPUT, INPUT_PATTERN, # RECURSIVE and so on. @@ -94,14 +95,14 @@ # # * 'doclib/dot' calls the real dot binary. If the resulting image is # more than 800 pixels wide, dot is called again, this time using -# the oposite rang direction (top-bottom vs. left-right). Then the -# image with the smaller width is selected and returned. +# the oposite rank direction (top-bottom vs. left-right). The image +# with the smaller width is selected and returned. # # * after doxygen is finished, the list of referenced tag-files is # checked. For each tag file the directory is found, where the # documentation is generated (by scanning the Doxyfile which is # repsonsible for building the tag file). For every tag file, the -# correct 'insstalldox' command is generated +# correct 'installdox' command is generated. # # * The stamp files are created # @@ -118,9 +119,9 @@ # namespace. # # * All html files are processed by 'doclib/html-munge.xsl'. However, -# since the documentation generated by doxygen is completely broken -# we need to preprocess the html files with a simple 'sed' script -# and 'tidy' before 'xsltproc' even accepts the html code. +# since the documentation generated by doxygen is completely invalid +# html we need to preprocess the html files with a simple 'sed' +# script and 'tidy' before 'xsltproc' even accepts the html code. # # * We use the generated xml output of doxygen to generate an XML # fragment for the global cross reference. This fragment is