Rev 6057: Merge-up the 2.4-all-reconnect-819604 in http://bazaar.launchpad.net/~jameinel/bzr/2.4-client-reconnect-819604
John Arbash Meinel
john at arbash-meinel.com
Fri Sep 14 07:39:02 UTC 2012
At http://bazaar.launchpad.net/~jameinel/bzr/2.4-client-reconnect-819604
------------------------------------------------------------
revno: 6057 [merge]
revision-id: john at arbash-meinel.com-20120914073824-tetu35y0t57nirg2
parent: john at arbash-meinel.com-20120914072249-rvpderuqqme7sy88
parent: john at arbash-meinel.com-20120914073238-b36mhl7zp3zypuui
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.4-client-reconnect-819604
timestamp: Fri 2012-09-14 11:38:24 +0400
message:
Merge-up the 2.4-all-reconnect-819604
modified:
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/smart/medium.py medium.py-20061103051856-rgu2huy59fkz902q-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 2012-09-14 07:22:49 +0000
+++ b/bzrlib/osutils.py 2012-09-14 07:38:24 +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
@@ -2044,7 +2045,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:
@@ -2116,12 +2117,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:51:29 +0000
+++ b/bzrlib/smart/medium.py 2012-09-14 07:38:24 +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
@@ -176,6 +176,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.
@@ -239,6 +247,8 @@
:param protocol: a SmartServerRequestProtocol.
"""
+ if protocol is None:
+ return
try:
self._serve_one_request_unguarded(protocol)
except KeyboardInterrupt:
@@ -737,7 +747,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')
@@ -792,6 +802,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):
@@ -914,6 +925,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/request.py'
--- a/bzrlib/smart/request.py 2011-10-10 13:51:29 +0000
+++ b/bzrlib/smart/request.py 2012-09-14 07:38:24 +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
@@ -564,8 +564,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')
@@ -688,5 +688,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-13 12:51:05 +0000
+++ b/bzrlib/tests/test_bundle.py 2012-09-14 07:38:24 +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-10-04 18:43:55 +0000
+++ b/bzrlib/tests/test_osutils.py 2012-09-14 07:38:24 +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
@@ -828,6 +828,45 @@
self.assertEqual('/etc/shadow', osutils._posix_normpath('///etc/shadow'))
+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