sock, self.port = bind_unused_port()
app = Application([('/', HelloWorldHandler)])
- server = HTTPServer(app, io_loop=self.server_ioloop)
- server.add_socket(sock)
+ self.server = HTTPServer(app, io_loop=self.server_ioloop)
+ self.server.add_socket(sock)
self.server_thread = threading.Thread(target=self.server_ioloop.start)
self.server_thread.start()
self.http_client = HTTPClient()
def tearDown(self):
- self.server_ioloop.add_callback(self.server_ioloop.stop)
+ def stop_server():
+ self.server.stop()
+ self.server_ioloop.stop()
+ self.server_ioloop.add_callback(stop_server)
self.server_thread.join()
self.http_client.close()
self.server_ioloop.close(all_fds=True)
SimpleAsyncHTTPClient(self.io_loop,
force_instance=True))
# different IOLoops use different objects
- io_loop2 = IOLoop()
- self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not
- SimpleAsyncHTTPClient(io_loop2))
+ with closing(IOLoop()) as io_loop2:
+ self.assertTrue(SimpleAsyncHTTPClient(self.io_loop) is not
+ SimpleAsyncHTTPClient(io_loop2))
def test_connection_limit(self):
with closing(self.create_client(max_clients=2)) as client:
def test_yield_in_with(self):
@gen.engine
def f():
- with StackContext(functools.partial(self.context, 'c1')):
- # This yield is a problem: the generator will be suspended
- # and the StackContext's __exit__ is not called yet, so
- # the context will be left on _state.contexts for anything
- # that runs before the yield resolves.
- yield gen.Task(self.io_loop.add_callback)
+ try:
+ with StackContext(functools.partial(self.context, 'c1')):
+ # This yield is a problem: the generator will be suspended
+ # and the StackContext's __exit__ is not called yet, so
+ # the context will be left on _state.contexts for anything
+ # that runs before the yield resolves.
+ yield gen.Task(self.io_loop.add_callback)
+ except StackContextInconsistentError:
+ # In python <= 3.3, this suspended generator is never garbage
+ # collected, so it remains suspended in the 'yield' forever.
+ # Starting in 3.4, it is made collectable by raising
+ # a GeneratorExit exception from the yield, which gets
+ # converted into a StackContextInconsistentError by the
+ # exit of the 'with' block.
+ pass
with self.assertRaises(StackContextInconsistentError):
f()
# As above, but with ExceptionStackContext instead of StackContext.
@gen.engine
def f():
- with ExceptionStackContext(lambda t, v, tb: False):
- yield gen.Task(self.io_loop.add_callback)
+ try:
+ with ExceptionStackContext(lambda t, v, tb: False):
+ yield gen.Task(self.io_loop.add_callback)
+ except StackContextInconsistentError:
+ pass
with self.assertRaises(StackContextInconsistentError):
f()