Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Commit

Permalink
unix: deduplicate socket creation code in tcp.c
Browse files Browse the repository at this point in the history
Incidentally fixes a rather obscure bug where uv_tcp_connect() reconnected
and leaked a file descriptor when the handle was already busy connecting,
handle->fd was zero (unlikely) and uv_tcp_connect() got called again.
  • Loading branch information
bnoordhuis committed Jun 29, 2012
1 parent e4a68bb commit 1a6b6b7
Showing 1 changed file with 31 additions and 54 deletions.
85 changes: 31 additions & 54 deletions src/unix/tcp.c
Expand Up @@ -34,6 +34,26 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* tcp) {
}


static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) {
int sockfd;

if (handle->fd != -1)
return 0;

sockfd = uv__socket(domain, SOCK_STREAM, 0);

if (sockfd == -1)
return uv__set_sys_error(handle->loop, errno);

if (uv__stream_open((uv_stream_t*)handle, sockfd, flags)) {
close(sockfd);
return -1;
}

return 0;
}


static int uv__bind(uv_tcp_t* tcp,
int domain,
struct sockaddr* addr,
Expand All @@ -44,23 +64,8 @@ static int uv__bind(uv_tcp_t* tcp,
saved_errno = errno;
status = -1;

if (tcp->fd < 0) {
if ((tcp->fd = uv__socket(domain, SOCK_STREAM, 0)) == -1) {
uv__set_sys_error(tcp->loop, errno);
goto out;
}

if (uv__stream_open((uv_stream_t*)tcp,
tcp->fd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
close(tcp->fd);
tcp->fd = -1;
status = -2;
goto out;
}
}

assert(tcp->fd >= 0);
if (maybe_new_socket(tcp, domain, UV_STREAM_READABLE|UV_STREAM_WRITABLE))
return -1;

tcp->delayed_error = 0;
if (bind(tcp->fd, addr, addrsize) == -1) {
Expand All @@ -84,26 +89,17 @@ static int uv__connect(uv_connect_t* req,
struct sockaddr* addr,
socklen_t addrlen,
uv_connect_cb cb) {
int sockfd;
int r;

assert(handle->type == UV_TCP);

if (handle->connect_req)
return uv__set_sys_error(handle->loop, EALREADY);

if (handle->fd <= 0) {
sockfd = uv__socket(addr->sa_family, SOCK_STREAM, 0);

if (sockfd == -1)
return uv__set_sys_error(handle->loop, errno);

if (uv__stream_open((uv_stream_t*)handle,
sockfd,
UV_STREAM_READABLE | UV_STREAM_WRITABLE)) {
close(sockfd);
return -1;
}
if (maybe_new_socket(handle,
addr->sa_family,
UV_STREAM_READABLE|UV_STREAM_WRITABLE)) {
return -1;
}

handle->delayed_error = 0;
Expand Down Expand Up @@ -231,33 +227,14 @@ int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name,


int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
int r;
if (tcp->delayed_error)
return uv__set_sys_error(tcp->loop, tcp->delayed_error);

if (tcp->delayed_error) {
uv__set_sys_error(tcp->loop, tcp->delayed_error);
if (maybe_new_socket(tcp, AF_INET, UV_STREAM_READABLE))
return -1;
}

if (tcp->fd < 0) {
if ((tcp->fd = uv__socket(AF_INET, SOCK_STREAM, 0)) == -1) {
uv__set_sys_error(tcp->loop, errno);
return -1;
}

if (uv__stream_open((uv_stream_t*)tcp, tcp->fd, UV_STREAM_READABLE)) {
close(tcp->fd);
tcp->fd = -1;
return -1;
}
}

assert(tcp->fd >= 0);

r = listen(tcp->fd, backlog);
if (r < 0) {
uv__set_sys_error(tcp->loop, errno);
return -1;
}
if (listen(tcp->fd, backlog))
return uv__set_sys_error(tcp->loop, errno);

tcp->connection_cb = cb;

Expand Down

0 comments on commit 1a6b6b7

Please sign in to comment.