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.
This commit is contained in:
Ben Darnell 2011-10-03 22:28:33 -07:00
parent 4b346bdde8
commit 420ad0869a
2 changed files with 16 additions and 3 deletions

View File

@ -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)

View File

@ -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]")