(isc__netievent_t *) ievent);
LOCK(&nsock->lock);
- while (!atomic_load(&nsock->listening)) {
+ while (!atomic_load(&nsock->listening) &&
+ !atomic_load(&nsock->listen_error)) {
WAIT(&nsock->cond, &nsock->lock);
}
UNLOCK(&nsock->lock);
(isc__netievent_tcplisten_t *) ev0;
isc_nmsocket_t *sock = ievent->sock;
struct sockaddr_storage sname;
- int r, snamelen = sizeof(sname);
+ int r, flags = 0, snamelen = sizeof(sname);
REQUIRE(isc__nm_in_netthread());
REQUIRE(sock->type == isc_nm_tcplistener);
/* It was never opened */
atomic_store(&sock->closed, true);
sock->result = isc__nm_uverr2result(r);
+ atomic_store(&sock->listen_error, true);
goto done;
}
+ if (sock->iface->addr.type.sa.sa_family == AF_INET6) {
+ flags = UV_TCP_IPV6ONLY;
+ }
- r = uv_tcp_bind(&sock->uv_handle.tcp, &sock->iface->addr.type.sa, 0);
+ r = uv_tcp_bind(&sock->uv_handle.tcp,
+ &sock->iface->addr.type.sa, flags);
if (r != 0) {
uv_close(&sock->uv_handle.handle, tcp_close_cb);
sock->result = isc__nm_uverr2result(r);
+ atomic_store(&sock->listen_error, true);
goto done;
}
* initially returning success even if bind() fails, and this
* could cause a deadlock later if we didn't check first.)
*/
- r = uv_tcp_getsockname(&sock->uv_handle.tcp, &sname, &snamelen);
+ r = uv_tcp_getsockname(&sock->uv_handle.tcp,
+ (struct sockaddr*) &sname, &snamelen);
if (r != 0) {
uv_close(&sock->uv_handle.handle, tcp_close_cb);
sock->result = isc__nm_uverr2result(r);
+ atomic_store(&sock->listen_error, true);
goto done;
}
(isc_nmsocket_t **)&sock->uv_handle.udp.data);
uv_udp_open(&sock->uv_handle.udp, sock->fd);
+ int flags = 0;
+ if (sock->iface->addr.type.sa.sa_family == AF_INET6) {
+ flags = UV_UDP_IPV6ONLY;
+ }
uv_udp_bind(&sock->uv_handle.udp,
- &sock->parent->iface->addr.type.sa, 0);
+ &sock->parent->iface->addr.type.sa, flags);
uv_recv_buffer_size(&sock->uv_handle.handle,
&(int){16 * 1024 * 1024});
uv_send_buffer_size(&sock->uv_handle.handle,