Parcourir la source

add error handling and a test for that

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac296@2649 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen il y a 14 ans
Parent
commit
9ce7db783c
2 fichiers modifiés avec 41 ajouts et 7 suppressions
  1. 22 7
      src/lib/cc/session.cc
  2. 19 0
      src/lib/cc/session_unittests.cc

+ 22 - 7
src/lib/cc/session.cc

@@ -39,6 +39,7 @@
 #include <sys/un.h>
 
 #include <boost/bind.hpp>
+#include <boost/optional.hpp>
 #include <boost/function.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 
@@ -85,7 +86,7 @@ private:
     // Sets the boolean pointed to by result to true, unless
     // the given error code is operation_aborted
     // Used as a callback for emulating sync reads with async calls
-    void setResult(bool* result, asio::error_code b);
+    void setResult(bool* result, asio::error_code* result_code, asio::error_code b);
 
 private:
     io_service& io_service_;
@@ -143,7 +144,11 @@ SessionImpl::readDataLength() {
 }
 
 void
-SessionImpl::setResult(bool* result, const asio::error_code b) {
+SessionImpl::setResult(bool* result, asio::error_code* result_code, const asio::error_code b) {
+    *result_code = b;
+
+    // if the 'error' is operation_aborted (i.e. a call to cancel()),
+    // we do not consider the read or the wait 'done'.
     if (b != asio::error::operation_aborted) {
         *result = true;
     }
@@ -153,18 +158,23 @@ void
 SessionImpl::readData(void* data, size_t datalen) {
     bool timer_result = false;
     bool read_result = false;
+    asio::error_code read_result_code;
+    asio::error_code timer_result_code;
     try {
         asio::async_read(socket_, asio::buffer(data, datalen),
                          boost::bind(&SessionImpl::setResult, this,
-                                     &read_result, _1));
+                                     &read_result, &read_result_code, _1));
         asio::deadline_timer timer(socket_.io_service());
     
         if (getTimeout() != 0) {
             timer.expires_from_now(boost::posix_time::milliseconds(getTimeout()));
             timer.async_wait(boost::bind(&SessionImpl::setResult,
-                                         this, &timer_result, _1));
+                                         this, &timer_result,
+                                         &timer_result_code, _1));
         }
-    
+
+        // wait until either we have read the data we want, or the
+        // timer expires
         while (!read_result && !timer_result) {
             socket_.io_service().run_one();
             if (read_result) {
@@ -173,9 +183,14 @@ SessionImpl::readData(void* data, size_t datalen) {
                 socket_.cancel();
             }
         }
-    
+        if (read_result_code) {
+            isc_throw(SessionError,
+                      "Error while reading data from cc session: " <<
+                      read_result_code.message());
+        }
         if (!read_result) {
-            isc_throw(SessionTimeout, "Timeout or error while reading data from cc session");
+            isc_throw(SessionTimeout,
+                      "Timeout or error while reading data from cc session");
         }
     } catch (const asio::system_error& asio_ex) {
         // to hide boost specific exceptions, we catch them explicitly

+ 19 - 0
src/lib/cc/session_unittests.cc

@@ -190,3 +190,22 @@ TEST(Session, connect_ok) {
     sess.establish("/tmp/mysock.sock");
 }
 
+TEST(Session, connect_ok2) {
+    asio::io_service my_io_service;
+    ::unlink("/tmp/mysock.sock");
+    Session sess(my_io_service);
+
+    // Create a fake socket in a smaller scope, so we can
+    // connect the session to it, but later calls on the
+    // underlying socket will fail
+    {
+        TestDomainSocket tds(my_io_service, "/tmp/mysock.sock");
+        tds.setSendLname();
+    
+        sess.establish("/tmp/mysock.sock");
+    }
+    
+    isc::data::ElementPtr env, msg;
+    EXPECT_THROW(sess.group_recvmsg(env, msg, false, -1), isc::cc::SessionError);
+}
+