your mail

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


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 failed (98: Address already in use)
> My understanding was that this error stems from [::] being 
> inclusive of, 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, 
as these two belong to different address families.  But in fact 
depending on v6only system (or socket) setting [::] may either 
include 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 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