unix: only set SO_REUSEADDR when bind() fails

Only call setsockopt() when the initial bind() fails with EADDRINUSE,
then retry.  Saves a system call in what is normally the common case.

PR-URL: https://github.com/libuv/libuv/pull/88
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
Ben Noordhuis 2014-12-27 18:02:53 +01:00
parent 025602da13
commit a9e95a33bc

View File

@ -62,6 +62,7 @@ int uv__tcp_bind(uv_tcp_t* tcp,
unsigned int flags) {
int err;
int on;
int fd;
/* Cannot set IPv6-only mode on non-IPv6 socket. */
if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6)
@ -73,26 +74,29 @@ int uv__tcp_bind(uv_tcp_t* tcp,
if (err)
return err;
on = 1;
if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
return -errno;
fd = tcp->io_watcher.fd;
#ifdef IPV6_V6ONLY
if (addr->sa_family == AF_INET6) {
on = (flags & UV_TCP_IPV6ONLY) != 0;
if (setsockopt(tcp->io_watcher.fd,
IPPROTO_IPV6,
IPV6_V6ONLY,
&on,
sizeof on) == -1) {
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
return -errno;
}
}
#endif
errno = 0;
if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE)
return -errno;
if (bind(fd, addr, addrlen)) {
if (errno != EADDRINUSE)
return -errno;
on = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
return -errno;
errno = 0;
if (bind(fd, addr, addrlen) && errno != EADDRINUSE)
return -errno;
}
tcp->delayed_error = -errno;
if (addr->sa_family == AF_INET6)