Socket: BUGFIX: Move incorrect v-function call out of FileBody destructor
g0dil [Wed, 6 Feb 2008 09:51:41 +0000 (09:51 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@670 270642c3-0616-0410-b53a-bc976706d245

Socket/FileHandle.cc
Socket/FileHandle.cci
Socket/FileHandle.hh
Socket/FileHandle.ih
Socket/SocketHandle.cc
Socket/SocketHandle.test.cc
Socket/SocketProtocol.cc
Socket/SocketProtocol.hh
Socket/SocketProtocol.test.hh
debian/rules
doclib/SConscript

index 2872469..4ce3835 100644 (file)
 #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)
index 9f82d08..79308ae 100644 (file)
@@ -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())
 {}
index 2ae609a..5b0e34d 100644 (file)
@@ -123,6 +123,7 @@ namespace senf {
         ///@{
 
         FileHandle();
+        ~FileHandle();
 
         // my default constructor
         // default copy constructor
index cdc775d..e87e319 100644 (file)
@@ -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;
index 14fd6b2..aa0cf61 100644 (file)
 #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
 
index e377f0b..709fb9f 100644 (file)
@@ -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////////////////////////////////////////
index e252603..ca28664 100644 (file)
@@ -33,6 +33,7 @@
 //#include "SocketProtocol.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
+
 prefix_ void senf::SocketProtocol::close()
     const
 {
index db71a83..72ddad5 100644 (file)
@@ -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
index 3ca682a..c5073f3 100644 (file)
@@ -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;
+        }
     };
 
 }}
index 911d1b8..b87c105 100755 (executable)
@@ -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' 
index 102709e..276ec2d 100644 (file)
@@ -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.
 #
 # * '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
 #
 #   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