Issue #711 resolved

"localhost" in config file mistakenly causes IP6 socket on Mac OS

Anonymous created an issue

Details: CherryPy 3.01, Mac OS 10.4.10, Python 2.51 (compiled from src)

The tutorial sample tut01_helloworld.py starts up normally with this message:

[29/Jul/2007:02:18:32] HTTP Serving HTTP on http://localhost:8080/

But that address fails to load in the browser. Firefox displays "Unable to connect. Firefox can't establish a connection to the server at localhost:8080."

After poking around a bit, I discovered that CP was mistakenly using IP6 sockets. Typing the address "http://[::1]:8080/" into Firefox DOES load the "Hello world!" page.

So here's what I think is happening. In _cpserver.py, line 213:

for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res

socket.getaddrinfo() is resolving "localhost" as an IP6 hostname instead of IP4. I don't know why this would happen, but it's probably specific to Mac OS. For what it's worth, there is no AF_UNSPEC defined in the socket.py file in my python installation.

Changing the config file to a numeric hostname fixes the problem, as follows:

server.socket_host = "127.0.0.1"

Perhaps a fix should put more robust code around the getaddrinfo() call to ensure that the correct socktype is returned on OS's with this quirk.

Reported by jeff@drunkenchipmunk.com

Comments (7)

  1. Anonymous

    Sorry, small correction: AF_UNSPEC is actually defined in socket on my system (Mac OS 10.4.10/python 2.5.1).

    Regardless, the bug issue is still valid.

  2. Robert Brewer

    As I understand it, there's no mistake: "localhost" is [http://www.faqs.org/rfcs/rfc2606.html defined] to be the loopback address(es), and both IPv4 and IPv6 have loopback addresses. If your system is set up to prefer the IPv6 address, then that's something for you to change on your system. Several references suggest changing /etc/hosts to do this:

  3. Anonymous

    Thanks for the useful references.

    For the benefit of others: commenting out the IPv6 localhost entry in /etc/hosts does indeed fix this issue. This seems to be the appropriate fix if you are not using IPv6.

    While I agree this is not a cherrypy bug, it might be useful to note this quirk in getaddrinfo() behavior somewhere in the documentation, since by default, Mac OS comes with IPv6 enabled. Despite the IPv4 entry appearing first in /etc/hosts, the list returned by socket.getaddrinfo() contains the IPv6 entry first. The man page for the getaddrinfo call does not indicate any guarantees about the order of records returned, so this may not be a bug per se. Nevertheless, it does cause unexpected behavior in cherrypy that typical Mac users with default net settings should be aware of.

    Also, maybe it'd be a good idea to log an informational msg when more than one valid record is returned by getaddrinfo() for a host.

  4. Anonymous

    And you will see it on most Linux out there too by default. This is not a defect, it's for the deployers to understand that if a system supports IPv6 and IPv4, it's more than likely than the former one will be chosen by the system.

  5. Log in to comment