From a9e95a33bc723dc42daea2fcde6dde1d4cc5efad Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 27 Dec 2014 18:02:53 +0100 Subject: [PATCH] unix: only set SO_REUSEADDR when bind() fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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é --- src/unix/tcp.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 8c19c1ab..e1803236 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -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)