Rev 6174: Re-order the loop a bit. Move the exception handling into the loop, so that we can handle EINTR. in http://bazaar.launchpad.net/~jameinel/bzr/drop-idle-connections-824797

John Arbash Meinel john at arbash-meinel.com
Wed Sep 21 11:47:59 UTC 2011


At http://bazaar.launchpad.net/~jameinel/bzr/drop-idle-connections-824797

------------------------------------------------------------
revno: 6174
revision-id: john at arbash-meinel.com-20110921114746-rxal7pr14l1a3gjn
parent: john at arbash-meinel.com-20110919105225-cn62n2zi3aj5efdm
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: drop-idle-connections-824797
timestamp: Wed 2011-09-21 13:47:46 +0200
message:
  Re-order the loop a bit. Move the exception handling into the loop, so that we can handle EINTR.
  
  Break out of the loop on 'xs'.
  
  Clean up the code a bit, remove comments in favor of doc strings, and hopefully
  reasonably easy-to-understand structure.
-------------- next part --------------
=== modified file 'bzrlib/smart/medium.py'
--- a/bzrlib/smart/medium.py	2011-09-19 10:52:25 +0000
+++ b/bzrlib/smart/medium.py	2011-09-21 11:47:46 +0000
@@ -282,37 +282,30 @@
         return protocol
 
     def _wait_on_descriptor(self, fd, timeout_seconds):
-        """select() on a file descriptor, waiting for nonblocking read()"""
-        # Use local variables to handle when the interpreter is shutting down
-        try:
-            # It looks like during the test suite, we close the server-side
-            # socket as part of 'shut down this server'. Depending on how
-            # we race with select.select, that either
-            # 1) Raises socket.error(EBADF) immediately
-            # 2) Occasionally (1 in 1000 or so) raises select.error(EBADF)
-            # 3) 1-in-3 or so times out, calling select.select immediately
-            #    afterwards seems to raise EBADF.
-            # I think what happens is select.select is unable to see the
-            # status of a file that is closed after it starts 'sleeping'.
-            t_end = time.time() + timeout_seconds
-            poll_timeout = min(timeout_seconds, self._client_poll_timeout)
-            rs = []
-            while not rs and time.time() < t_end:
+        """select() on a file descriptor, waiting for nonblocking read()
+
+        :return: Did we time out before fd is ready to read? (Note that ready
+            to read may be either that there is data to be read, or that the
+            descriptor is already closed, or there is a pending error.)
+        """
+        t_end = time.time() + timeout_seconds
+        poll_timeout = min(timeout_seconds, self._client_poll_timeout)
+        rs = xs = None
+        while not rs and not xs and time.time() < t_end:
+            try:
                 rs, _, xs = select.select([fd], [], [fd], poll_timeout)
-        except (select.error, socket.error) as e:
-            err = getattr(e, 'errno', None)
-            if err is None:
-                # select.error doesn't have 'errno', it just has args[0]
-                if getattr(e, 'args', None) is not None:
+            except (select.error, socket.error) as e:
+                err = getattr(e, 'errno', None)
+                if err is None and getattr(e, 'args', None) is not None:
+                    # select.error doesn't have 'errno', it just has args[0]
                     err = e.args[0]
-            if err in _bad_file_descriptor:
-                # If we are told at this point that socket is no longer a valid
-                # socket, just return 'without timeout'
-                return False
-            raise
+                if err in _bad_file_descriptor:
+                    return False    # Not a socket indicates read() will fail
+                elif err == errno.EINTR:
+                    # Interrupted, keep looping.
+                    continue
+                raise
         if rs or xs:
-            # Either we can read without blocking, or there is a pending error.
-            # Either way, we didn't time out, so try to read from it.
             return False
         return True
 



More information about the bazaar-commits mailing list