BIND 10 trac2398, updated. af81d772421d616ff4d219a0feb371a9e2ec3edf [2398] Unify two sending methods a bit

BIND 10 source code commits bind10-changes at lists.isc.org
Tue Nov 27 13:10:23 UTC 2012


The branch, trac2398 has been updated
       via  af81d772421d616ff4d219a0feb371a9e2ec3edf (commit)
       via  8e6846495d72600013021d331c8138943f1d4c14 (commit)
      from  65962eeed622a6fc92b2e47ac881fbe7b54d3bf2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit af81d772421d616ff4d219a0feb371a9e2ec3edf
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Nov 27 14:09:20 2012 +0100

    [2398] Unify two sending methods a bit
    
    By moving the error-checking into __send_data(), both send_prepared_msg() and __process_write() now only need to check the return value

commit 8e6846495d72600013021d331c8138943f1d4c14
Author: Jelte Jansen <jelte at isc.org>
Date:   Tue Nov 27 12:00:52 2012 +0100

    [2398] Add second control socket pair to test msgq
    
    And remove internal timeouts in msgq again; actions are now only triggered by available data, as in the original

-----------------------------------------------------------------------

Summary of changes:
 src/bin/msgq/msgq.py.in         |   84 +++++++++++++++++----------------------
 src/bin/msgq/tests/msgq_test.py |   34 ++++++++--------
 2 files changed, 55 insertions(+), 63 deletions(-)

-----------------------------------------------------------------------
diff --git a/src/bin/msgq/msgq.py.in b/src/bin/msgq/msgq.py.in
index 303ea22..f640c6c 100755
--- a/src/bin/msgq/msgq.py.in
+++ b/src/bin/msgq/msgq.py.in
@@ -340,6 +340,17 @@ class MsgQ:
         self.send_prepared_msg(sock, self.preparemsg(env, msg))
 
     def __send_data(self, sock, data):
+        """
+        Send a piece of data to the given socket.
+        Parameters:
+        sock: The socket to send to
+        data: The list of bytes to send
+        Returns:
+        An integer or None. If an integer (which can be 0), it signals
+        the number of bytes sent. If None, the socket appears to have
+        been closed on the other end, and it has been killed on this
+        side too.
+        """
         try:
             # We set the socket nonblocking, MSG_DONTWAIT doesn't exist
             # on some OSes
@@ -350,6 +361,13 @@ class MsgQ:
                             errno.EWOULDBLOCK,
                             errno.EINTR ]:
                 return 0
+            elif e.errno in [ errno.EPIPE,
+                              errno.ECONNRESET,
+                              errno.ENOBUFS ]:
+                print("[b10-msgq] " + errno.errorcode[e.errno] +
+                      " on send, dropping message and closing connection")
+                self.kill_socket(sock.fileno(), sock)
+                return None
             else:
                 raise e
         finally:
@@ -362,23 +380,12 @@ class MsgQ:
         if fileno in self.sendbuffs:
             amount_sent = 0
         else:
-            try:
-                amount_sent = self.__send_data(sock, msg)
-            except socket.error as sockerr:
-                # in the case the other side seems gone, or unable to handle
-                # life, kill the socket and drop the send action
-                if sockerr.errno in [ errno.EPIPE,
-                                      errno.ECONNRESET,
-                                      errno.ENOBUFS
-                                    ]:
-                    print("[b10-msgq] " + errno.errorcode[sockerr.errno] +
-                          " on send, dropping message and closing connection")
-                    self.kill_socket(fileno, sock)
-                    return
-                else:
-                    raise
+            amount_sent = self.__send_data(sock, msg)
+            if amount_sent is None:
+                # Socket has been killed, drop the send
+                return
 
-        # Still something to send
+        # Still something to send, add it to outgoing queue
         if amount_sent < len(msg):
             now = time.clock()
             # Append it to buffer (but check the data go away)
@@ -402,32 +409,19 @@ class MsgQ:
         # Try to send some data from the buffer
         (_, msg) = self.sendbuffs[fileno]
         sock = self.sockets[fileno]
-        try:
-            amount_sent = self.__send_data(sock, msg)
-        except socket.error as sockerr:
-            # in the case the other side seems gone, or unable to handle
-            # life, kill the socket and drop the send action
-            if sockerr.errno in [ errno.EPIPE,
-                                  errno.ECONNRESET,
-                                  errno.ENOBUFS
-                                ]:
-                print("[b10-msgq] " + errno.errorcode[sockerr.errno] +
-                      " on send, dropping message and closing connection")
-                self.kill_socket(fileno, sock)
-                return
-            else:
-                raise
-        # Keep the rest
-        msg = msg[amount_sent:]
-        if len(msg) == 0:
-            # If there's no more, stop requesting for write availability
-            if self.poller:
-                self.poller.register(fileno, select.POLLIN)
+        amount_sent = self.__send_data(sock, msg)
+        if amount_sent is not None:
+            # Keep the rest
+            msg = msg[amount_sent:]
+            if len(msg) == 0:
+                # If there's no more, stop requesting for write availability
+                if self.poller:
+                    self.poller.register(fileno, select.POLLIN)
+                else:
+                    self.delete_kqueue_socket(sock, True)
+                del self.sendbuffs[fileno]
             else:
-                self.delete_kqueue_socket(sock, True)
-            del self.sendbuffs[fileno]
-        else:
-            self.sendbuffs[fileno] = (time.clock(), msg)
+                self.sendbuffs[fileno] = (time.clock(), msg)
 
     def newlname(self):
         """Generate a unique connection identifier for this socket.
@@ -493,9 +487,7 @@ class MsgQ:
             try:
                 # Poll with a timeout so that every once in a while,
                 # the loop checks for self.running.
-                # Timeout set to 2 seconds so as not to block too long,
-                # but also not cause too many loop cycles
-                events = self.poller.poll(2000)
+                events = self.poller.poll()
             except select.error as err:
                 if err.args[0] == errno.EINTR:
                     events = []
@@ -517,9 +509,7 @@ class MsgQ:
         while self.running:
             # Check with a timeout so that every once in a while,
             # the loop checks for self.running.
-            # Timeout set to 2 seconds so as not to block too long,
-            # but also not cause too many loop cycles
-            events = self.kqueue.control(None, 10, 2)
+            events = self.kqueue.control(None, 10)
             if not events:
                 raise RuntimeError('serve: kqueue returned no events')
 
diff --git a/src/bin/msgq/tests/msgq_test.py b/src/bin/msgq/tests/msgq_test.py
index b6426b4..4ed0441 100644
--- a/src/bin/msgq/tests/msgq_test.py
+++ b/src/bin/msgq/tests/msgq_test.py
@@ -323,15 +323,23 @@ class SendNonblock(unittest.TestCase):
             data = data + data
         self.send_many(data)
 
-    def do_send(self, write, read, expect_arrive=True,
-                expect_send_exception=None):
+    def do_send(self, write, read, control_write, control_read,
+                expect_arrive=True, expect_send_exception=None):
         """
         Makes a msgq object that is talking to itself,
         run it in a separate thread so we can use and
         test run().
+        It is given two sets of connected sockets; write/read, and
+        control_write/control_read. The former may be throwing errors
+        and mangle data to test msgq. The second is mainly used to
+        send msgq the stop command.
+        (Note that the terms 'read' and 'write' are from the msgq
+        point of view, so the test itself writes to 'control_read')
         Parameters:
         write: a socket that is used to send the data to
         read: a socket that is used to read the data from
+        control_write: a second socket for communication with msgq
+        control_read: a second socket for communication with msgq
         expect_arrive: if True, the read socket is read from, and the data
                        that is read is expected to be the same as the data
                        that has been sent to the write socket.
@@ -348,6 +356,7 @@ class SendNonblock(unittest.TestCase):
         msgq.listen_socket = DummySocket
         msgq.setup_poller()
         msgq.register_socket(write)
+        msgq.register_socket(control_write)
         # Queue the message for sending
         msgq.sendmsg(write, env, msg)
 
@@ -362,19 +371,9 @@ class SendNonblock(unittest.TestCase):
             self.assertEqual(env, recv_env)
             self.assertEqual(msg, recv_msg)
 
-            # expect_arrive also suggests everything should
-            # still be working, so a stop command should also
-            # be processed correctly
-            msg = msgq.preparemsg({"type" : "stop"})
-            read.sendall(msg)
-        else:
-            # OK, then bluntly call stop itself
-            # First give it a chance to handle any remaining events.
-            # 1 second arbitrarily chosen to hopefully be long enough
-            # yet not bog down the tests too much.
-            msgq_thread.join(1.0)
-            # If it didn't crash, stop it now.
-            msgq.stop()
+        # Tell msgq to stop
+        msg = msgq.preparemsg({"type" : "stop"})
+        control_read.sendall(msg)
 
         # Wait for thread to stop if it hasn't already.
         # Put in a (long) timeout; the thread *should* stop, but if it
@@ -409,10 +408,13 @@ class SendNonblock(unittest.TestCase):
                                send_exception is raised by BadSocket.
         """
         (write, read) = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
+        (control_write, control_read) = socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM)
         badwrite = BadSocket(write, raise_on_send, send_exception)
-        self.do_send(badwrite, read, expect_answer, expect_send_exception)
+        self.do_send(badwrite, read, control_write, control_read, expect_answer, expect_send_exception)
         write.close()
         read.close()
+        control_write.close()
+        control_read.close()
 
     def test_send_raise_recoverable(self):
         """



More information about the bind10-changes mailing list