From: Ben Darnell Date: Tue, 4 Oct 2011 05:28:33 +0000 (-0700) Subject: Errors from socket.connect() should be treated the same way as async failures. X-Git-Tag: v2.1.1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=420ad0869a6a964ab6a7d31401de8d8cf2fedd25;p=thirdparty%2Ftornado.git Errors from socket.connect() should be treated the same way as async failures. On freebsd non-blocking connect() may return certain errors (such as ECONNREFUSED from localhost) immediately instead of returning EINPROGRESS and then giving the error later. Also improve the test for ipv6 compatibility, since freebsd returns a different error than other platforms when ipv6 is not available. --- diff --git a/tornado/iostream.py b/tornado/iostream.py index 0027a82bf..6c9e61c9c 100644 --- a/tornado/iostream.py +++ b/tornado/iostream.py @@ -119,9 +119,18 @@ class IOStream(object): try: self.socket.connect(address) except socket.error, e: - # In non-blocking mode connect() always raises an exception + # In non-blocking mode we expect connect() to raise an + # exception with EINPROGRESS or EWOULDBLOCK. + # + # On freebsd, other errors such as ECONNREFUSED may be + # returned immediately when attempting to connect to + # localhost, so handle them the same way as an error + # reported later in _handle_connect. if e.args[0] not in (errno.EINPROGRESS, errno.EWOULDBLOCK): - raise + logging.warning("Connect error on fd %d: %s", + self.socket.fileno(), e) + self.close() + return self._connect_callback = stack_context.wrap(callback) self._add_io_state(self.io_loop.WRITE) diff --git a/tornado/test/simple_httpclient_test.py b/tornado/test/simple_httpclient_test.py index f6d7235ae..cc23d620c 100644 --- a/tornado/test/simple_httpclient_test.py +++ b/tornado/test/simple_httpclient_test.py @@ -141,11 +141,15 @@ class SimpleHTTPClientTestCase(AsyncHTTPTestCase, LogTrapTestCase): self.assertEqual(str(response.error), "HTTP 599: Timeout") def test_ipv6(self): + if not socket.has_ipv6: + # python compiled without ipv6 support, so skip this test + return try: self.http_server.listen(self.get_http_port(), address='::1') except socket.gaierror, e: if e.errno == socket.EAI_ADDRFAMILY: - # ipv6 is not configured on this system, so skip this test + # python supports ipv6, but it's not configured on the network + # interface, so skip this test. return raise url = self.get_url("/hello").replace("localhost", "[::1]")