Rev 5669: Merge 2.2-all-reconnect-819604, and resolve the copyright conflict. in http://bazaar.launchpad.net/~jameinel/bzr/2.3-all-reconnect-819604

John Arbash Meinel john at arbash-meinel.com
Fri Sep 14 07:17:20 UTC 2012


At http://bazaar.launchpad.net/~jameinel/bzr/2.3-all-reconnect-819604

------------------------------------------------------------
revno: 5669 [merge]
revision-id: john at arbash-meinel.com-20120914071644-6b9bsadisrurx5up
parent: john at arbash-meinel.com-20120914071425-7of2o3m9mmqgskx1
parent: john at arbash-meinel.com-20120914070833-om0l2637zl7u1vg3
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.3-all-reconnect-819604
timestamp: Fri 2012-09-14 11:16:44 +0400
message:
  Merge 2.2-all-reconnect-819604, and resolve the copyright conflict.
modified:
  bzrlib/osutils.py              osutils.py-20050309040759-eeaff12fbf77ac86
  bzrlib/smart/medium.py         medium.py-20061103051856-rgu2huy59fkz902q-1
  bzrlib/smart/protocol.py       protocol.py-20061108035435-ot0lstk2590yqhzr-1
  bzrlib/smart/request.py        request.py-20061108095550-gunadhxmzkdjfeek-1
  bzrlib/tests/test_bundle.py    test.py-20050630184834-092aa401ab9f039c
  bzrlib/tests/test_osutils.py   test_osutils.py-20051201224856-e48ee24c12182989
-------------- next part --------------
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2011-10-10 13:43:54 +0000
+++ b/bzrlib/osutils.py	2012-09-14 07:16:44 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005-2011 Canonical Ltd
+# Copyright (C) 2005-2012 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
 # and need the former on windows
 import shutil
 from shutil import rmtree
+import signal
 import socket
 import subprocess
 # We need to import both tempfile and mkdtemp as we export the later on posix
@@ -2001,7 +2002,7 @@
 # data at once.
 MAX_SOCKET_CHUNK = 64 * 1024
 
-_end_of_stream_errors = [errno.ECONNRESET]
+_end_of_stream_errors = [errno.ECONNRESET, errno.EPIPE, errno.EINVAL]
 for _eno in ['WSAECONNRESET', 'WSAECONNABORTED']:
     _eno = getattr(errno, _eno, None)
     if _eno is not None:
@@ -2073,12 +2074,19 @@
     while sent_total < byte_count:
         try:
             sent = sock.send(buffer(bytes, sent_total, MAX_SOCKET_CHUNK))
-        except socket.error, e:
+        except (socket.error, IOError), e:
+            if e.args[0] in _end_of_stream_errors:
+                raise errors.ConnectionReset(
+                    "Error trying to write to socket", e)
             if e.args[0] != errno.EINTR:
                 raise
         else:
+            if sent == 0:
+                raise errors.ConnectionReset('Sending to %s returned 0 bytes'
+                                             % (sock,))
             sent_total += sent
-            report_activity(sent, 'write')
+            if report_activity is not None:
+                report_activity(sent, 'write')
 
 
 def connect_socket(address):

=== modified file 'bzrlib/smart/medium.py'
--- a/bzrlib/smart/medium.py	2011-10-10 13:38:17 +0000
+++ b/bzrlib/smart/medium.py	2012-09-14 07:08:33 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2011 Canonical Ltd
+# Copyright (C) 2006-2012 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -177,6 +177,14 @@
         ui.ui_factory.report_transport_activity(self, bytes, direction)
 
 
+_bad_file_descriptor = (errno.EBADF,)
+if sys.platform == 'win32':
+    # Given on Windows if you pass a closed socket to select.select. Probably
+    # also given if you pass a file handle to select.
+    WSAENOTSOCK = 10038
+    _bad_file_descriptor += (WSAENOTSOCK,)
+
+
 class SmartServerStreamMedium(SmartMedium):
     """Handles smart commands coming over a stream.
 
@@ -240,6 +248,8 @@
 
         :param protocol: a SmartServerRequestProtocol.
         """
+        if protocol is None:
+            return
         try:
             self._serve_one_request_unguarded(protocol)
         except KeyboardInterrupt:
@@ -738,7 +748,7 @@
         except IOError, e:
             if e.errno in (errno.EINVAL, errno.EPIPE):
                 raise errors.ConnectionReset(
-                    "Error trying to write to subprocess:\n%s" % (e,))
+                    "Error trying to write to subprocess", e)
             raise
         self._report_activity(len(bytes), 'write')
 
@@ -793,6 +803,7 @@
         # method before calling the super init.
         SmartClientStreamMedium.__init__(self, base)
         self._vendor = vendor
+        self._bzr_remote_path = bzr_remote_path
         self._ssh_connection = None
 
     def __repr__(self):
@@ -915,6 +926,20 @@
         SmartClientSocketMedium.__init__(self, base)
         self._host = host
         self._port = port
+        self._socket = None
+
+    def _accept_bytes(self, bytes):
+        """See SmartClientMedium.accept_bytes."""
+        self._ensure_connection()
+        osutils.send_all(self._socket, bytes, self._report_activity)
+
+    def disconnect(self):
+        """See SmartClientMedium.disconnect()."""
+        if not self._connected:
+            return
+        self._socket.close()
+        self._socket = None
+        self._connected = False
 
     def _ensure_connection(self):
         """Connect this medium if not already connected."""

=== modified file 'bzrlib/smart/protocol.py'
--- a/bzrlib/smart/protocol.py	2011-10-10 13:38:17 +0000
+++ b/bzrlib/smart/protocol.py	2012-09-14 07:08:33 +0000
@@ -654,7 +654,7 @@
         """Make a remote call with a readv array.
 
         The body is encoded with one line per readv offset pair. The numbers in
-        each pair are separated by a comma, and no trailing \n is emitted.
+        each pair are separated by a comma, and no trailing \\n is emitted.
         """
         if 'hpss' in debug.debug_flags:
             mutter('hpss call w/readv: %s', repr(args)[1:-1])
@@ -1330,7 +1330,7 @@
         """Make a remote call with a readv array.
 
         The body is encoded with one line per readv offset pair. The numbers in
-        each pair are separated by a comma, and no trailing \n is emitted.
+        each pair are separated by a comma, and no trailing \\n is emitted.
         """
         if 'hpss' in debug.debug_flags:
             mutter('hpss call w/readv: %s', repr(args)[1:-1])

=== modified file 'bzrlib/smart/request.py'
--- a/bzrlib/smart/request.py	2011-10-10 13:36:30 +0000
+++ b/bzrlib/smart/request.py	2012-09-14 07:08:33 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2006-2011 Canonical Ltd
+# Copyright (C) 2006-2012 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -134,7 +134,7 @@
         It will return a SmartServerResponse if the command does not expect a
         body.
 
-        :param *args: the arguments of the request.
+        :param args: the arguments of the request.
         """
         self._check_enabled()
         return self.do(*args)
@@ -556,8 +556,8 @@
     'Branch.set_parent_location', 'bzrlib.smart.branch',
     'SmartServerBranchRequestSetParentLocation', info='idem')
 request_handlers.register_lazy(
-    'Branch.unlock', 'bzrlib.smart.branch', 'SmartServerBranchRequestUnlock',
-    info='semi')
+    'Branch.unlock', 'bzrlib.smart.branch',
+    'SmartServerBranchRequestUnlock', info='semi')
 request_handlers.register_lazy(
     'BzrDir.cloning_metadir', 'bzrlib.smart.bzrdir',
     'SmartServerBzrDirRequestCloningMetaDir', info='read')
@@ -680,5 +680,5 @@
 request_handlers.register_lazy(
     'stat', 'bzrlib.smart.vfs', 'StatRequest', info='read')
 request_handlers.register_lazy(
-    'Transport.is_readonly', 'bzrlib.smart.request', 'SmartServerIsReadonly',
-    info='read')
+    'Transport.is_readonly', 'bzrlib.smart.request',
+    'SmartServerIsReadonly', info='read')

=== modified file 'bzrlib/tests/test_bundle.py'
--- a/bzrlib/tests/test_bundle.py	2011-05-12 20:26:05 +0000
+++ b/bzrlib/tests/test_bundle.py	2012-09-14 07:16:44 +0000
@@ -1852,20 +1852,23 @@
         self.sock.bind(('127.0.0.1', 0))
         self.sock.listen(1)
         self.port = self.sock.getsockname()[1]
+        self.stopping = threading.Event()
         self.thread = threading.Thread(
             name='%s (port %d)' % (self.__class__.__name__, self.port),
             target=self.accept_and_close)
         self.thread.start()
 
     def accept_and_close(self):
-        conn, addr = self.sock.accept()
-        conn.shutdown(socket.SHUT_RDWR)
-        conn.close()
+        while not self.stopping.isSet():
+            conn, addr = self.sock.accept()
+            conn.shutdown(socket.SHUT_RDWR)
+            conn.close()
 
     def get_url(self):
         return 'bzr://127.0.0.1:%d/' % (self.port,)
 
     def stop_server(self):
+        self.stopping.set()
         try:
             # make sure the thread dies by connecting to the listening socket,
             # just in case the test failed to do so.

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2011-06-15 15:21:54 +0000
+++ b/bzrlib/tests/test_osutils.py	2012-09-14 07:16:44 +0000
@@ -799,6 +799,45 @@
         self.assertEqual(None, osutils.safe_file_id(None))
 
 
+class TestSendAll(tests.TestCase):
+
+    def test_send_with_disconnected_socket(self):
+        class DisconnectedSocket(object):
+            def __init__(self, err):
+                self.err = err
+            def send(self, content):
+                raise self.err
+            def close(self):
+                pass
+        # All of these should be treated as ConnectionReset
+        errs = []
+        for err_cls in (IOError, socket.error):
+            for errnum in osutils._end_of_stream_errors:
+                errs.append(err_cls(errnum))
+        for err in errs:
+            sock = DisconnectedSocket(err)
+            self.assertRaises(errors.ConnectionReset,
+                osutils.send_all, sock, 'some more content')
+
+    def test_send_with_no_progress(self):
+        # See https://bugs.launchpad.net/bzr/+bug/1047309
+        # It seems that paramiko can get into a state where it doesn't error,
+        # but it returns 0 bytes sent for requests over and over again.
+        class NoSendingSocket(object):
+            def __init__(self):
+                self.call_count = 0
+            def send(self, bytes):
+                self.call_count += 1
+                if self.call_count > 100:
+                    # Prevent the test suite from hanging
+                    raise RuntimeError('too many calls')
+                return 0
+        sock = NoSendingSocket()
+        self.assertRaises(errors.ConnectionReset,
+                          osutils.send_all, sock, 'content')
+        self.assertEqual(1, sock.call_count)
+
+
 class TestWin32Funcs(tests.TestCase):
     """Test that _win32 versions of os utilities return appropriate paths."""
 



More information about the bazaar-commits mailing list