Rev 6054: Fix a naughty race in test_server_crash_while_responding in file:///home/vila/src/bzr/bugs/869366-test-server-race/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Fri Oct 7 14:15:34 UTC 2011
At file:///home/vila/src/bzr/bugs/869366-test-server-race/
------------------------------------------------------------
revno: 6054
revision-id: v.ladeuil+lp at free.fr-20111007141534-jmwit7px0qoz1bbm
parent: v.ladeuil+lp at free.fr-20111007134112-seo2r1u8y0pf97a7
fixes bug: https://launchpad.net/bugs/869366
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 869366-test-server-race
timestamp: Fri 2011-10-07 16:15:34 +0200
message:
Fix a naughty race in test_server_crash_while_responding
-------------- next part --------------
=== modified file 'bzrlib/cethread.py'
--- a/bzrlib/cethread.py 2011-05-19 09:32:38 +0000
+++ b/bzrlib/cethread.py 2011-10-07 14:15:34 +0000
@@ -126,6 +126,8 @@
super(CatchingExceptionThread, self).run()
except:
self.exception = sys.exc_info()
+ print '\nthread %r, sync: %r see %r' % (
+ self, self.sync_event, self.exception[0],)
finally:
# Make sure the calling thread is released
self.sync_event.set()
=== modified file 'bzrlib/tests/test_test_server.py'
--- a/bzrlib/tests/test_test_server.py 2011-10-07 13:41:12 +0000
+++ b/bzrlib/tests/test_test_server.py 2011-10-07 14:15:34 +0000
@@ -169,22 +169,27 @@
self.assertRaises(CantConnect, server.stop_server)
def test_server_crash_while_responding(self):
- sync = threading.Event()
- sync.clear()
+ # We need to ensure the exception will be raised
+ will_raise = threading.Event()
+ will_raise.clear()
+ # We need to ensure the exception has been caught
+ caught = threading.Event()
+ caught.clear()
+ print 'will_raise: %r, caught: %r\n' % (will_raise, caught)
# The thread that will serve the client
self.connection_thread = None
- test = self # So the handler can set connection_thread
class FailToRespond(Exception):
pass
class FailingDuringResponseHandler(TCPConnectionHandler):
- def handle_connection(self):
- req = self.rfile.readline()
- # Capture the thread and make it use 'sync' so we can wait on
+ def handle_connection(request):
+ req = request.rfile.readline()
+ # Capture the thread and make it use 'caught' so we can wait on
# the even set when the exception is caught
- test.connection_thread = threading.currentThread()
- test.connection_thread.set_sync_event(sync)
+ self.connection_thread = threading.currentThread()
+ self.connection_thread.set_sync_event(caught)
+ will_raise.set()
raise FailToRespond()
server = self.get_server(
@@ -192,7 +197,10 @@
client = self.get_client()
client.connect((server.host, server.port))
client.write('ping\n')
- sync.wait()
+ # Wait for the connection to succeed and be processed
+ will_raise.wait()
+ # Wait for the exception to be caught
+ caught.wait()
# 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
@@ -203,21 +211,25 @@
self.connection_thread.pending_exception)
def test_exception_swallowed_while_serving(self):
- sync = threading.Event()
- sync.clear()
+ # We need to ensure the exception will be raised
+ will_raise = threading.Event()
+ will_raise.clear()
+ # We need to ensure the exception has been caught
+ caught = threading.Event()
+ caught.clear()
# The thread that will serve the client
self.connection_thread = None
- test = self # So the handler can set connection_thread
class CantServe(Exception):
pass
class FailingWhileServingConnectionHandler(TCPConnectionHandler):
def handle(request):
- # Capture the thread and make it use 'sync' so we can wait on
+ # Capture the thread and make it use 'caught' so we can wait on
# the even set when the exception is caught
- test.connection_thread = threading.currentThread()
- test.connection_thread.set_sync_event(sync)
+ self.connection_thread = threading.currentThread()
+ self.connection_thread.set_sync_event(caught)
+ will_raise.set()
raise CantServe()
server = self.get_server(
@@ -227,10 +239,14 @@
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 connection to succeed and be processed
+ will_raise.wait()
+ # Wait for the exception to be caught
+ caught.wait()
# The connection wasn't served properly but the exception should have
# been swallowed (see test_server_crash_while_responding remark about
# http://pad.lv/869366 explaining why we can't check the server thread
- # here).
+ # 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()
More information about the bazaar-commits
mailing list