Rev 6206: (jam) Merge bzr-2.4 into bzr.dev, resolving small conflicts. in file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/
Patch Queue Manager
pqm at pqm.ubuntu.com
Mon Oct 10 14:26:04 UTC 2011
At file:///srv/pqm.bazaar-vcs.org/archives/thelove/bzr/%2Btrunk/
------------------------------------------------------------
revno: 6206 [merge]
revision-id: pqm at pqm.ubuntu.com-20111010142604-n77hphh9k3lfn668
parent: pqm at pqm.ubuntu.com-20111010085906-wh17ij8w2k3bxs6x
parent: john at arbash-meinel.com-20111010135922-wanbhsy9i42zm6w9
committer: Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2011-10-10 14:26:04 +0000
message:
(jam) Merge bzr-2.4 into bzr.dev, resolving small conflicts.
modified:
bzrlib/tests/test_server.py test_server.py-20100209163834-im1ozfuenfmqaa2m-1
bzrlib/tests/test_test_server.py test_test_server.py-20100601152414-r8rln0ok7514pcoz-1
doc/en/release-notes/bzr-2.4.txt bzr2.4.txt-20110114053217-k7ym9jfz243fddjm-1
=== modified file 'bzrlib/tests/test_server.py'
--- a/bzrlib/tests/test_server.py 2011-10-05 15:01:54 +0000
+++ b/bzrlib/tests/test_server.py 2011-10-10 13:59:22 +0000
@@ -289,7 +289,6 @@
def serve(self):
self.serving = True
- self.stopped.clear()
# We are listening and ready to accept connections
self.started.set()
try:
@@ -464,6 +463,8 @@
if debug_threads():
sys.stderr.write('Client thread %s started\n' % (t.name,))
# If an exception occured during the thread start, it will get raised.
+ # In rare cases, an exception raised during the request processing may
+ # also get caught here (see http://pad.lv/869366)
t.pending_exception()
# The following methods are called by the main thread
@@ -519,7 +520,7 @@
sync_event=self.server.started,
target=self.run_server)
self._server_thread.start()
- # Wait for the server thread to start (i.e release the lock)
+ # Wait for the server thread to start (i.e. release the lock)
self.server.started.wait()
# Get the real address, especially the port
self.host, self.port = self.server.server_address
=== modified file 'bzrlib/tests/test_test_server.py'
--- a/bzrlib/tests/test_test_server.py 2011-10-03 08:15:39 +0000
+++ b/bzrlib/tests/test_test_server.py 2011-10-10 13:59:22 +0000
@@ -112,9 +112,6 @@
for name in
('TestingTCPServer', 'TestingThreadingTCPServer')]
- # Set by load_tests()
- server_class = None
-
def get_server(self, server_class=None, connection_handler_class=None):
if server_class is not None:
self.server_class = server_class
@@ -202,16 +199,26 @@
self.assertRaises(CantConnect, server.stop_server)
def test_server_crash_while_responding(self):
- sync = threading.Event()
- sync.clear()
+ # We want to ensure the exception has been caught
+ caught = threading.Event()
+ caught.clear()
+ # The thread that will serve the client, this needs to be an attribute
+ # so the handler below can modify it when it's executed (it's
+ # instantiated when the request is processed)
+ self.connection_thread = None
+
class FailToRespond(Exception):
pass
class FailingDuringResponseHandler(TCPConnectionHandler):
- def handle_connection(self):
- req = self.readline()
- threading.currentThread().set_sync_event(sync)
+ def handle_connection(request):
+ req = request.readline()
+ # Capture the thread and make it use 'caught' so we can wait on
+ # the even that will be set when the exception is caught. We
+ # also capture the thread to know where to look.
+ self.connection_thread = threading.currentThread()
+ self.connection_thread.set_sync_event(caught)
raise FailToRespond()
server = self.get_server(
@@ -219,22 +226,46 @@
client = self.get_client()
client.connect((server.host, server.port))
client.write('ping\n')
- sync.wait()
+ # Wait for the exception to be caught
+ caught.wait()
self.assertEqual('', client.read()) # connection closed
- self.assertRaises(FailToRespond, server.pending_exception)
+ # Check that the connection thread did catch the exception,
+ # http://pad.lv/869366 was wrongly checking the server thread which
+ # works for TestingTCPServer where the connection is handled in the
+ # same thread than the server one but is racy for
+ # TestingThreadingTCPServer where the server thread may be in a
+ # blocking accept() call (or not).
+ try:
+ self.connection_thread.pending_exception()
+ except FailToRespond:
+ # Great, the test succeeded
+ pass
+ else:
+ # If the exception is not in the connection thread anymore, it's in
+ # the server's one.
+ server.server.stopped.wait()
+ # The exception is available now
+ self.assertRaises(FailToRespond, server.pending_exception)
def test_exception_swallowed_while_serving(self):
- sync = threading.Event()
- sync.clear()
+ # We need to ensure the exception has been caught
+ caught = threading.Event()
+ caught.clear()
+ # The thread that will serve the client, this needs to be an attribute
+ # so the handler below can access it when it's executed (it's
+ # instantiated when the request is processed)
+ self.connection_thread = None
class CantServe(Exception):
pass
class FailingWhileServingConnectionHandler(TCPConnectionHandler):
- def handle(self):
- # We want to sync with the thread that is serving the
- # connection.
- threading.currentThread().set_sync_event(sync)
+ def handle(request):
+ # Capture the thread and make it use 'caught' so we can wait on
+ # the even that will be set when the exception is caught. We
+ # also capture the thread to know where to look.
+ self.connection_thread = threading.currentThread()
+ self.connection_thread.set_sync_event(caught)
raise CantServe()
server = self.get_server(
@@ -244,11 +275,16 @@
client = self.get_client()
# Connect to the server so the exception is raised there
client.connect((server.host, server.port))
- # Wait for the exception to propagate.
- sync.wait()
+ # Wait for the exception to be caught
+ caught.wait()
self.assertEqual('', client.read()) # connection closed
# The connection wasn't served properly but the exception should have
- # been swallowed.
+ # been swallowed (see test_server_crash_while_responding remark about
+ # http://pad.lv/869366 explaining why we can't check the server thread
+ # here). More precisely, the exception *has* been caught and captured
+ # but it is cleared when joining the thread (or trying to acquire the
+ # exception) and as such won't propagate to the server thread.
+ self.connection_thread.pending_exception()
server.pending_exception()
def test_handle_request_closes_if_it_doesnt_process(self):
=== modified file 'doc/en/release-notes/bzr-2.4.txt'
--- a/doc/en/release-notes/bzr-2.4.txt 2011-10-06 16:41:45 +0000
+++ b/doc/en/release-notes/bzr-2.4.txt 2011-10-10 13:59:22 +0000
@@ -75,6 +75,9 @@
suite. This can include new facilities for writing tests, fixes to
spurious test failures and changes to the way things should be tested.
+* Fix the race for TestingThreadingTCPServer in
+ test_server_crash_while_responding. (Vincent Ladeuil, #869366)
+
* Really corrupt the pack file without depending on a special length or value.
(Vincent Ladeuil, #807032)
More information about the bazaar-commits
mailing list