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.
This commit is contained in:
parent
e4a68bb5cb
commit
1a6b6b781c
@ -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;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user