From 1a6b6b781c1b30ed6ff694d934c7dac4f975cf81 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Fri, 29 Jun 2012 18:43:44 +0200 Subject: [PATCH] unix: deduplicate socket creation code in tcp.c 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. --- src/unix/tcp.c | 85 ++++++++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 54 deletions(-) diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 223bb048..233be825 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -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, @@ -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) { @@ -84,7 +89,6 @@ 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); @@ -92,18 +96,10 @@ static int uv__connect(uv_connect_t* req, 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; @@ -231,33 +227,14 @@ out: 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;