On Tue, Feb 22, 2005 at 10:52:57PM -0800, Justin Erenkrantz wrote: > No idea why I'm suddenly hitting this, but in preparation for 2.1.3, I > spent another one of my patented hours searching for bugs in httpd that end > up being bugs in the perl-framework tests. =( > > perl-framework generates Listen directives in the order of: > 'Listen 0.0.0.0:8529' > > For me, this causes errors like: > (48)Address already in use: make_sock: could not bind to address > 0.0.0.0:8531 > no listening sockets available, shutting down > Unable to open logs > > On Mac OS X 10.3.8 (7.8.0 via uname -r), getaddrinfo() without AI_PASSIVE > can return duplicate IP addresses. This leads to the error condition that > causes the failure. And, based on my reading of the docs, I'm not sure > that's patently incorrect behavior on Darwin's part: that's 0.0.0.0 for > both the localhost and the network card.
But there is no way to differentiate between any different interfaces for the address (without doing magic), so I would say that is a resolver misfeature. "Listen 0.0.0.0:<port>" should always work because there's no other way to configure httpd to bind only to "all IPv4 addresses on the local host with port X" (right?), which is certainly a valid and useful thing to do. I think httpd should work around this: does something like the attached work? (tested only to compile ;) Not necessarily the best place to put this logic. > The issue with this is that wildcard IP addresses aren't really supposed to > be explicit in Listen statements. httpd has a bunch of logic for inferring > the right IP wildcards - trying to out-guess can lead to real badness. > Specifically, this mucks with APR's ability to set AI_PASSIVE - which is > required for use with address that we will later call bind() on - i.e. our > listeners. So, Listen with an IP address should only be used for real > addresses. The problem was that 2.0.x will only accept connections to IPv6 addresses with a single "Listen <port>"; but since LWP doesn't support IPv6, that doesn't work for httpd-test. The alternative is to start getting complicated but with the different logic in 2.0 and 2.1 I think it would be better to avoid this. joe
Index: server/listen.c =================================================================== --- server/listen.c (revision 154212) +++ server/listen.c (working copy) @@ -353,6 +353,18 @@ continue; } #endif + /* Skip duplicates addresses returned for an AI_PASSIVE + * lookup for 0.0.0.0 on Darwin: */ + if (previous != NULL + && lr->bind_addr->family == APR_INET + && lr->bind_addr->sa.sin.sin_addr.s_addr == INADDR_ANY + && previous->bind_addr->family == APR_INET + && previous->bind_addr->sa.sin.sin_addr.s_addr == INADDR_ANY + && lr->bind_addr->port == previous->bind_addr->port) { + previous->next = lr->next; + continue; + } + if (make_sock(pool, lr) == APR_SUCCESS) { ++num_open; lr->active = 1;