Permalink
Browse files

unix: only set SO_REUSEADDR on tcp listen sockets

Avoid the extra syscall, it's a no-op for non-listening sockets.

At least, it should be - it remains to be investigated if a FreeBSD kernel bug
affects ephemeral port allocation inside connect(). See [1] for details.

[1] http://www.freebsd.org/cgi/query-pr.cgi?pr=174087
  • Loading branch information...
1 parent b4168cd commit a385ae4f59aeb10b24e60c3d6880a38a645635bd @bnoordhuis bnoordhuis committed Dec 9, 2012
Showing with 10 additions and 26 deletions.
  1. +0 −8 src/unix/stream.c
  2. +10 −18 src/unix/tcp.c
View
@@ -101,18 +101,10 @@ void uv__stream_init(uv_loop_t* loop,
int uv__stream_open(uv_stream_t* stream, int fd, int flags) {
- socklen_t yes;
-
assert(fd >= 0);
stream->flags |= flags;
if (stream->type == UV_TCP) {
- /* Reuse the port address if applicable. */
- yes = 1;
-
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1)
- return uv__set_sys_error(stream->loop, errno);
-
if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1))
return uv__set_sys_error(stream->loop, errno);
View
@@ -58,29 +58,21 @@ static int uv__bind(uv_tcp_t* tcp,
int domain,
struct sockaddr* addr,
int addrsize) {
- int saved_errno;
- int status;
-
- saved_errno = errno;
- status = -1;
+ int on;
if (maybe_new_socket(tcp, domain, UV_STREAM_READABLE|UV_STREAM_WRITABLE))
return -1;
- tcp->delayed_error = 0;
- if (bind(tcp->io_watcher.fd, addr, addrsize) == -1) {
- if (errno == EADDRINUSE) {
- tcp->delayed_error = errno;
- } else {
- uv__set_sys_error(tcp->loop, errno);
- goto out;
- }
- }
- status = 0;
+ on = 1;
+ if (setsockopt(tcp->io_watcher.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
+ return uv__set_sys_error(tcp->loop, errno);
-out:
- errno = saved_errno;
- return status;
+ errno = 0;
+ if (bind(tcp->io_watcher.fd, addr, addrsize) && errno != EADDRINUSE)
+ return uv__set_sys_error(tcp->loop, errno);
+
+ tcp->delayed_error = errno;
+ return 0;
}

0 comments on commit a385ae4

Please sign in to comment.