your mail

Maxim Dounin mdounin at mdounin.ru
Thu Jun 2 13:32:50 MSD 2011


Hello!

On Wed, Jun 01, 2011 at 10:33:42AM -0400, Les Aker wrote:

> I've found what appears to be a bug in the handling of listen 
> directives for ipv4 and ipv6.
> 
> When running two vhosts, one of which listens on [::], the other 
> on localhost, nginx will fail with this error:
> 2011/06/01 10:12:35 [emerg] 9750#0: bind() to 127.0.0.1:80 failed (98: Address already in use)
> My understanding was that this error stems from [::] being 
> inclusive of 127.0.0.1, causing nginx to attempt to bind it 
> twice.
> However, replacing the `listen localhost;` with `listen [::1];` 
> removes the error, despite the fact that [::1] is also included 
> within [::].  -- Les Aker

Linux, I suppose?  There are two problems here:

1. Linux doesn't allow multiple bind()'s on the same port, even 
with setsockopt(SO_REUSEADDR).

2. nginx doesn't expect [::] to conflict with / include 127.0.0.1, 
as these two belong to different address families.  But in fact 
depending on v6only system (or socket) setting [::] may either 
include 127.0.0.1 or not.

With [::] and [::1] nginx expects conflict to happen and 
workarounds it for Linux by using single bind() on [::] and 
getsockaddr() call on each new connection.  With [::] and 
127.0.0.1 it doesn't (see (2)) and that's why you see conflict.

Simple solution is to explicitly listen on ipv4 and ipv6 (with 
v6only option) sockets, like this:

    listen *:80;
    listen [::]:80 ipv6only=on;

(actually, this is how it works on other operating systems 
with v6only being on by default, and either on Linux with 
appropriate sysctl being set)

Maxim Dounin



More information about the nginx mailing list