From 86f4872dd64d28bbf551c4b2b178f5d69cce4515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 31 Mar 2021 18:32:32 +0200 Subject: [PATCH] isc_nm_*connect() always return via callback The isc_nm_*connect() functions were refactored to always return the connection status via the connect callback instead of sometimes returning the hard failure directly (for example, when the socket could not be created, or when the network manager was shutting down). This commit changes the connect functions in all the network manager modules, and also makes the necessary refactoring changes in places where the connect functions are called. --- bin/rndc/rndc.c | 7 +- bin/tests/test_client.c | 42 ++-- lib/dns/xfrin.c | 12 +- lib/isc/include/isc/netmgr.h | 12 +- lib/isc/netmgr/http.c | 39 +++- lib/isc/netmgr/netmgr.c | 13 +- lib/isc/netmgr/tcp.c | 41 ++-- lib/isc/netmgr/tcpdns.c | 43 ++-- lib/isc/netmgr/tlsdns.c | 43 ++-- lib/isc/netmgr/tlsstream.c | 33 +-- lib/isc/netmgr/udp.c | 45 ++-- lib/isc/tests/doh_test.c | 102 ++++----- lib/isc/tests/netmgr_test.c | 416 +++++++++++------------------------ lib/isc/tests/tls_test.c | 49 +++-- lib/isc/tests/uv_wrap.h | 8 +- 15 files changed, 349 insertions(+), 556 deletions(-) diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index bc3d124328..47c862e24f 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -574,7 +574,6 @@ rndc_connected(isc_nmhandle_t *handle, isc_result_t result, void *arg) { static void rndc_startconnect(isc_sockaddr_t *addr) { - isc_result_t result; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t *local = NULL; @@ -600,10 +599,8 @@ rndc_startconnect(isc_sockaddr_t *addr) { } atomic_fetch_add_relaxed(&connects, 1); - DO("create connection", - isc_nm_tcpconnect(netmgr, (isc_nmiface_t *)local, - (isc_nmiface_t *)addr, rndc_connected, &rndc_ccmsg, - 10000, 0)); + isc_nm_tcpconnect(netmgr, (isc_nmiface_t *)local, (isc_nmiface_t *)addr, + rndc_connected, &rndc_ccmsg, 10000, 0); } static void diff --git a/bin/tests/test_client.c b/bin/tests/test_client.c index 4056e537f3..c145115af8 100644 --- a/bin/tests/test_client.c +++ b/bin/tests/test_client.c @@ -235,8 +235,6 @@ parse_options(int argc, char **argv) { } } - INSIST(optind < argc); - { struct addrinfo hints = { .ai_family = family, @@ -281,7 +279,7 @@ parse_options(int argc, char **argv) { isc_sockaddr_format(&sockaddr_remote, buf, sizeof(buf)); - printf("to %s, %d workers\n", buf, workers); + printf(" to %s, %d workers\n", buf, workers); } static void @@ -378,16 +376,16 @@ connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { isc_nmhandle_t *readhandle = NULL; REQUIRE(handle != NULL); - REQUIRE(eresult == ISC_R_SUCCESS); UNUSED(cbarg); + fprintf(stderr, "ECHO_CLIENT:%s:%s\n", __func__, + isc_result_totext(eresult)); + if (eresult != ISC_R_SUCCESS) { kill(getpid(), SIGTERM); return; } - fprintf(stderr, "ECHO_CLIENT:%s\n", __func__); - isc_nmhandle_attach(handle, &readhandle); isc_nm_read(handle, read_cb, readhandle); isc_nm_send(handle, &message, send_cb, NULL); @@ -422,28 +420,23 @@ sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf, static void run(void) { - isc_result_t result; - switch (protocol) { case UDP: - result = isc_nm_udpconnect(netmgr, - (isc_nmiface_t *)&sockaddr_local, - (isc_nmiface_t *)&sockaddr_remote, - connect_cb, NULL, timeout, 0); + isc_nm_udpconnect(netmgr, (isc_nmiface_t *)&sockaddr_local, + (isc_nmiface_t *)&sockaddr_remote, connect_cb, + NULL, timeout, 0); break; case TCP: - result = isc_nm_tcpdnsconnect(netmgr, - (isc_nmiface_t *)&sockaddr_local, - (isc_nmiface_t *)&sockaddr_remote, - connect_cb, NULL, timeout, 0); + isc_nm_tcpdnsconnect(netmgr, (isc_nmiface_t *)&sockaddr_local, + (isc_nmiface_t *)&sockaddr_remote, + connect_cb, NULL, timeout, 0); break; case DOT: { isc_tlsctx_createclient(&tls_ctx); - result = isc_nm_tlsdnsconnect( - netmgr, (isc_nmiface_t *)&sockaddr_local, - (isc_nmiface_t *)&sockaddr_remote, connect_cb, NULL, - timeout, 0, tls_ctx); + isc_nm_tlsdnsconnect(netmgr, (isc_nmiface_t *)&sockaddr_local, + (isc_nmiface_t *)&sockaddr_remote, + connect_cb, NULL, timeout, 0, tls_ctx); break; } case HTTP_GET: @@ -460,16 +453,15 @@ run(void) { if (is_https) { isc_tlsctx_createclient(&tls_ctx); } - result = isc_nm_httpconnect( - netmgr, (isc_nmiface_t *)&sockaddr_local, - (isc_nmiface_t *)&sockaddr_remote, req_url, is_post, - connect_cb, NULL, tls_ctx, timeout, 0); + isc_nm_httpconnect(netmgr, (isc_nmiface_t *)&sockaddr_local, + (isc_nmiface_t *)&sockaddr_remote, req_url, + is_post, connect_cb, NULL, tls_ctx, timeout, + 0); } break; default: INSIST(0); ISC_UNREACHABLE(); } - REQUIRE(result == ISC_R_SUCCESS); waitforsignal(); diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index c0e06cf71a..03ccb115a2 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -894,17 +894,17 @@ xfrin_start(dns_xfrin_ctx_t *xfr) { */ switch (transport_type) { case DNS_TRANSPORT_TCP: - CHECK(isc_nm_tcpdnsconnect( - xfr->netmgr, (isc_nmiface_t *)&xfr->sourceaddr, - (isc_nmiface_t *)&xfr->masteraddr, xfrin_connect_done, - connect_xfr, 30000, 0)); + isc_nm_tcpdnsconnect(xfr->netmgr, + (isc_nmiface_t *)&xfr->sourceaddr, + (isc_nmiface_t *)&xfr->masteraddr, + xfrin_connect_done, connect_xfr, 30000, 0); break; case DNS_TRANSPORT_TLS: CHECK(isc_tlsctx_createclient(&xfr->tlsctx)); - CHECK(isc_nm_tlsdnsconnect( + isc_nm_tlsdnsconnect( xfr->netmgr, (isc_nmiface_t *)&xfr->sourceaddr, (isc_nmiface_t *)&xfr->masteraddr, xfrin_connect_done, - connect_xfr, 30000, 0, xfr->tlsctx)); + connect_xfr, 30000, 0, xfr->tlsctx); break; default: INSIST(0); diff --git a/lib/isc/include/isc/netmgr.h b/lib/isc/include/isc/netmgr.h index 215b0150b0..a89436345f 100644 --- a/lib/isc/include/isc/netmgr.h +++ b/lib/isc/include/isc/netmgr.h @@ -207,7 +207,7 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb, * can then be freed automatically when the handle is destroyed. */ -isc_result_t +void isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize); @@ -318,7 +318,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_nmiface_t *iface, * */ -isc_result_t +void isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize); @@ -481,16 +481,16 @@ isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface, size_t extrahandlesize, int backlog, isc_quota_t *quota, isc_tlsctx_t *sslctx, isc_nmsocket_t **sockp); -isc_result_t +void isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, isc_tlsctx_t *ctx, unsigned int timeout, size_t extrahandlesize); -isc_result_t +void isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize); -isc_result_t +void isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize, isc_tlsctx_t *sslctx); @@ -508,7 +508,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, * 'cb'. */ -isc_result_t +void isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, const char *uri, bool POST, isc_nm_cb_t cb, void *cbarg, isc_tlsctx_t *ctx, unsigned int timeout, diff --git a/lib/isc/netmgr/http.c b/lib/isc/netmgr/http.c index 51e7096ec1..f1595eee94 100644 --- a/lib/isc/netmgr/http.c +++ b/lib/isc/netmgr/http.c @@ -1147,12 +1147,11 @@ error: isc__nmsocket_detach(&http_sock); } -isc_result_t +void isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, const char *uri, bool post, isc_nm_cb_t cb, void *cbarg, isc_tlsctx_t *tlsctx, unsigned int timeout, size_t extrahandlesize) { - isc_result_t result; isc_nmiface_t local_interface; isc_nmsocket_t *sock = NULL; @@ -1176,12 +1175,34 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, sock->result = ISC_R_DEFAULT; sock->connect_cb = cb; sock->connect_cbarg = cbarg; + atomic_init(&sock->client, true); + + if (isc__nm_closing(sock)) { + isc__nm_uvreq_t *req = isc__nm_uvreq_get(mgr, sock); + + req->cb.connect = cb; + req->cbarg = cbarg; + req->peer = peer->addr; + req->local = local->addr; + req->handle = isc__nmhandle_get(sock, &req->peer, + &sock->iface->addr); + + if (isc__nm_in_netthread()) { + sock->tid = isc_nm_tid(); + } + + isc__nmsocket_clearcb(sock); + isc__nm_connectcb(sock, req, ISC_R_CANCELED, true); + isc__nmsocket_prep_destroy(sock); + isc__nmsocket_detach(&sock); + return; + } + sock->h2 = (isc_nmsocket_h2_t){ .connect.uri = isc_mem_strdup(mgr->mctx, uri), .connect.post = post, .connect.tlsctx = tlsctx }; ISC_LINK_INIT(&sock->h2, link); - atomic_init(&sock->client, true); /* * We need to prevent the interface object data from going out of @@ -1193,16 +1214,12 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, } if (tlsctx != NULL) { - result = isc_nm_tlsconnect(mgr, local, peer, - transport_connect_cb, sock, tlsctx, - timeout, 0); + isc_nm_tlsconnect(mgr, local, peer, transport_connect_cb, sock, + tlsctx, timeout, 0); } else { - result = isc_nm_tcpconnect(mgr, local, peer, - transport_connect_cb, sock, timeout, - 0); + isc_nm_tcpconnect(mgr, local, peer, transport_connect_cb, sock, + timeout, 0); } - - return (result); } static isc_result_t diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 64b51aa9be..407637081f 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1871,7 +1871,7 @@ isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) { } worker = &sock->mgr->workers[sock->tid]; - INSIST(!worker->recvbuf_inuse); + INSIST(!worker->recvbuf_inuse || sock->type == isc_nm_udpsocket); buf->base = worker->recvbuf; buf->len = size; @@ -2335,12 +2335,13 @@ isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq, .req = uvreq, .result = eresult }; isc__nm_async_connectcb(NULL, (isc__netievent_t *)&ievent); - return; + } else { + isc__netievent_connectcb_t *ievent = + isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq, + eresult); + isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid], + (isc__netievent_t *)ievent); } - isc__netievent_connectcb_t *ievent = isc__nm_get_netievent_connectcb( - sock->mgr, sock, uvreq, eresult); - isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid], - (isc__netievent_t *)ievent); } void diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index dc25b9800d..4c5e45167c 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -141,11 +141,6 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { RUNTIME_CHECK(r == 0); uv_handle_set_data((uv_handle_t *)&sock->timer, sock); - if (isc__nm_closing(sock)) { - result = ISC_R_CANCELED; - goto error; - } - r = uv_tcp_open(&sock->uv_handle.tcp, sock->fd); if (r != 0) { isc__nm_closesocket(sock->fd); @@ -180,7 +175,6 @@ tcp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { done: result = isc__nm_uverr2result(r); -error: LOCK(&sock->lock); sock->result = result; SIGNAL(&sock->cond); @@ -215,7 +209,7 @@ isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ev0) { if (sock->fd != (uv_os_sock_t)(-1)) { isc__nm_tcp_close(sock); } - isc__nm_uvreq_put(&req, sock); + isc__nm_connectcb(sock, req, result, true); } /* @@ -286,7 +280,7 @@ error: isc__nm_failed_connect_cb(sock, req, result); } -isc_result_t +void isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize) { @@ -295,7 +289,6 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc__netievent_tcpconnect_t *ievent = NULL; isc__nm_uvreq_t *req = NULL; sa_family_t sa_family; - uv_os_sock_t fd; REQUIRE(VALID_NM(mgr)); REQUIRE(local != NULL); @@ -303,22 +296,13 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, sa_family = peer->addr.type.sa.sa_family; - /* - * The socket() call can fail spuriously on FreeBSD 12, so we need to - * handle the failure early and gracefully. - */ - result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &fd); - if (result != ISC_R_SUCCESS) { - return (result); - } - sock = isc_mem_get(mgr->mctx, sizeof(*sock)); isc__nmsocket_init(sock, mgr, isc_nm_tcpsocket, local); sock->extrahandlesize = extrahandlesize; sock->connect_timeout = timeout; sock->result = ISC_R_DEFAULT; - sock->fd = fd; + sock->fd = (uv_os_sock_t)-1; atomic_init(&sock->client, true); req = isc__nm_uvreq_get(mgr, sock); @@ -328,6 +312,18 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, req->local = local->addr; req->handle = isc__nmhandle_get(sock, &req->peer, &sock->iface->addr); + result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock->fd); + if (result != ISC_R_SUCCESS) { + if (isc__nm_in_netthread()) { + sock->tid = isc_nm_tid(); + } + isc__nmsocket_clearcb(sock); + isc__nm_connectcb(sock, req, result, false); + atomic_store(&sock->closed, true); + isc__nmsocket_detach(&sock); + return; + } + ievent = isc__nm_get_netievent_tcpconnect(mgr, sock, req); if (isc__nm_in_netthread()) { @@ -343,17 +339,12 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, (isc__netievent_t *)ievent); } LOCK(&sock->lock); - result = sock->result; - while (result == ISC_R_DEFAULT) { + while (sock->result == ISC_R_DEFAULT) { WAIT(&sock->cond, &sock->lock); - result = sock->result; } atomic_store(&sock->active, true); BROADCAST(&sock->scond); UNLOCK(&sock->lock); - INSIST(result != ISC_R_DEFAULT); - - return (result); } static uv_os_sock_t diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index dbdb21332d..b2dba833ed 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -180,9 +180,10 @@ isc__nm_async_tcpdnsconnect(isc__networker_t *worker, isc__netievent_t *ev0) { result = tcpdns_connect_direct(sock, req); if (result != ISC_R_SUCCESS) { + isc__nmsocket_clearcb(sock); + isc__nm_connectcb(sock, req, result, true); atomic_store(&sock->active, false); isc__nm_tcpdns_close(sock); - isc__nm_uvreq_put(&req, sock); } /* @@ -251,7 +252,7 @@ error: isc__nm_failed_connect_cb(sock, req, result); } -isc_result_t +void isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize) { @@ -260,7 +261,6 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc__netievent_tcpdnsconnect_t *ievent = NULL; isc__nm_uvreq_t *req = NULL; sa_family_t sa_family; - uv_os_sock_t fd; REQUIRE(VALID_NM(mgr)); REQUIRE(local != NULL); @@ -268,27 +268,14 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, sa_family = peer->addr.type.sa.sa_family; - /* - * The socket() call can fail spuriously on FreeBSD 12, so we need to - * handle the failure early and gracefully. - */ - result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &fd); - if (result != ISC_R_SUCCESS) { - return (result); - } - sock = isc_mem_get(mgr->mctx, sizeof(*sock)); isc__nmsocket_init(sock, mgr, isc_nm_tcpdnssocket, local); sock->extrahandlesize = extrahandlesize; sock->connect_timeout = timeout; sock->result = ISC_R_DEFAULT; - sock->fd = fd; atomic_init(&sock->client, true); - result = isc__nm_socket_connectiontimeout(fd, 120 * 1000); /* 2 mins */ - RUNTIME_CHECK(result == ISC_R_SUCCESS); - req = isc__nm_uvreq_get(mgr, sock); req->cb.connect = cb; req->cbarg = cbarg; @@ -296,6 +283,22 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, req->local = local->addr; req->handle = isc__nmhandle_get(sock, &req->peer, &sock->iface->addr); + result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock->fd); + if (result != ISC_R_SUCCESS) { + if (isc__nm_in_netthread()) { + sock->tid = isc_nm_tid(); + } + isc__nmsocket_clearcb(sock); + isc__nm_connectcb(sock, req, result, true); + atomic_store(&sock->closed, true); + isc__nmsocket_detach(&sock); + return; + } + + /* 2 minute timeout */ + result = isc__nm_socket_connectiontimeout(sock->fd, 120 * 1000); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + ievent = isc__nm_get_netievent_tcpdnsconnect(mgr, sock, req); if (isc__nm_in_netthread()) { @@ -310,18 +313,14 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc__nm_enqueue_ievent(&mgr->workers[sock->tid], (isc__netievent_t *)ievent); } + LOCK(&sock->lock); - result = sock->result; - while (result == ISC_R_DEFAULT) { + while (sock->result == ISC_R_DEFAULT) { WAIT(&sock->cond, &sock->lock); - result = sock->result; } atomic_store(&sock->active, true); BROADCAST(&sock->scond); UNLOCK(&sock->lock); - INSIST(result != ISC_R_DEFAULT); - - return (result); } static uv_os_sock_t diff --git a/lib/isc/netmgr/tlsdns.c b/lib/isc/netmgr/tlsdns.c index c7aba2cd35..fe437bf83b 100644 --- a/lib/isc/netmgr/tlsdns.c +++ b/lib/isc/netmgr/tlsdns.c @@ -196,9 +196,10 @@ isc__nm_async_tlsdnsconnect(isc__networker_t *worker, isc__netievent_t *ev0) { result = tlsdns_connect_direct(sock, req); if (result != ISC_R_SUCCESS) { + isc__nmsocket_clearcb(sock); + isc__nm_connectcb(sock, req, result, true); atomic_store(&sock->active, false); isc__nm_tlsdns_close(sock); - isc__nm_uvreq_put(&req, sock); } /* @@ -302,7 +303,7 @@ error: isc__nm_failed_connect_cb(sock, req, result); } -isc_result_t +void isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize, isc_tlsctx_t *sslctx) { @@ -311,7 +312,6 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc__netievent_tlsdnsconnect_t *ievent = NULL; isc__nm_uvreq_t *req = NULL; sa_family_t sa_family; - uv_os_sock_t fd; REQUIRE(VALID_NM(mgr)); REQUIRE(local != NULL); @@ -320,29 +320,15 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, sa_family = peer->addr.type.sa.sa_family; - /* - * The socket() call can fail spuriously on FreeBSD 12, so we - * need to handle the failure early and gracefully. - */ - result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &fd); - if (result != ISC_R_SUCCESS) { - return (result); - } - sock = isc_mem_get(mgr->mctx, sizeof(*sock)); isc__nmsocket_init(sock, mgr, isc_nm_tlsdnssocket, local); sock->extrahandlesize = extrahandlesize; sock->connect_timeout = timeout; sock->result = ISC_R_DEFAULT; - sock->fd = fd; sock->tls.ctx = sslctx; - atomic_init(&sock->client, true); - result = isc__nm_socket_connectiontimeout(fd, 120 * 1000); /* 2 mins */ - RUNTIME_CHECK(result == ISC_R_SUCCESS); - req = isc__nm_uvreq_get(mgr, sock); req->cb.connect = cb; req->cbarg = cbarg; @@ -350,6 +336,22 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, req->local = local->addr; req->handle = isc__nmhandle_get(sock, &req->peer, &sock->iface->addr); + result = isc__nm_socket(sa_family, SOCK_STREAM, 0, &sock->fd); + if (result != ISC_R_SUCCESS) { + if (isc__nm_in_netthread()) { + sock->tid = isc_nm_tid(); + } + isc__nmsocket_clearcb(sock); + isc__nm_connectcb(sock, req, result, true); + atomic_store(&sock->closed, true); + isc__nmsocket_detach(&sock); + return; + } + + /* 2 minute timeout */ + result = isc__nm_socket_connectiontimeout(sock->fd, 120 * 1000); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + ievent = isc__nm_get_netievent_tlsdnsconnect(mgr, sock, req); if (isc__nm_in_netthread()) { @@ -365,17 +367,12 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, (isc__netievent_t *)ievent); } LOCK(&sock->lock); - result = sock->result; - while (result == ISC_R_DEFAULT) { + while (sock->result == ISC_R_DEFAULT) { WAIT(&sock->cond, &sock->lock); - result = sock->result; } atomic_store(&sock->active, true); BROADCAST(&sock->scond); UNLOCK(&sock->lock); - INSIST(result != ISC_R_DEFAULT); - - return (result); } static uv_os_sock_t diff --git a/lib/isc/netmgr/tlsstream.c b/lib/isc/netmgr/tlsstream.c index bf9c5f9ce5..27a6bfcadb 100644 --- a/lib/isc/netmgr/tlsstream.c +++ b/lib/isc/netmgr/tlsstream.c @@ -835,13 +835,12 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock) { } } -isc_result_t +void isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, SSL_CTX *ctx, unsigned int timeout, size_t extrahandlesize) { isc_nmsocket_t *nsock = NULL, *tsock = NULL; isc__netievent_tlsconnect_t *ievent = NULL; - isc_result_t result = ISC_R_DEFAULT; #if defined(NETMGR_TRACE) && defined(NETMGR_TRACE_VERBOSE) fprintf(stderr, "TLS: isc_nm_tlsconnect(): in net thread: %s\n", isc__nm_in_netthread() ? "yes" : "no"); @@ -880,20 +879,14 @@ isc_nm_tlsconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, } LOCK(&nsock->lock); - result = nsock->result; - while (result == ISC_R_DEFAULT) { + while (nsock->result == ISC_R_DEFAULT) { WAIT(&nsock->cond, &nsock->lock); - result = nsock->result; } atomic_store(&nsock->active, true); BROADCAST(&nsock->scond); UNLOCK(&nsock->lock); INSIST(VALID_NMSOCK(nsock)); isc__nmsocket_detach(&tsock); - - INSIST(result != ISC_R_DEFAULT); - - return (result); } static void @@ -936,6 +929,11 @@ isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) { UNUSED(worker); + if (isc__nm_closing(tlssock)) { + result = ISC_R_CANCELED; + goto error; + } + /* * We need to initialize SSL now to reference SSL_CTX properly. */ @@ -948,20 +946,11 @@ isc__nm_async_tlsconnect(isc__networker_t *worker, isc__netievent_t *ev0) { tlssock->tid = isc_nm_tid(); tlssock->tlsstream.state = TLS_INIT; - result = isc_nm_tcpconnect(worker->mgr, (isc_nmiface_t *)&ievent->local, - (isc_nmiface_t *)&ievent->peer, - tcp_connected, tlssock, - tlssock->connect_timeout, 0); + isc_nm_tcpconnect(worker->mgr, (isc_nmiface_t *)&ievent->local, + (isc_nmiface_t *)&ievent->peer, tcp_connected, + tlssock, tlssock->connect_timeout, 0); - /* - * Sometimes on Linux, socket creation might fail if there are - * already too many socket descriptors. In such a case the - * connect callback is not going to be called. - */ - if (result != ISC_R_SUCCESS) { - goto error; - } - update_result(tlssock, result); + update_result(tlssock, ISC_R_SUCCESS); return; error: diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 9485fb76d5..02981f2723 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -617,7 +617,6 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { r = uv_udp_open(&sock->uv_handle.udp, sock->fd); if (r != 0) { - isc__nm_closesocket(sock->fd); isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]); goto done; } @@ -702,7 +701,7 @@ isc__nm_async_udpconnect(isc__networker_t *worker, isc__netievent_t *ev0) { if (result != ISC_R_SUCCESS) { atomic_store(&sock->active, false); isc__nm_udp_close(sock); - isc__nm_uvreq_put(&req, sock); + isc__nm_connectcb(sock, req, result, true); } else { /* * The callback has to be called after the socket has been @@ -717,7 +716,7 @@ isc__nm_async_udpconnect(isc__networker_t *worker, isc__netievent_t *ev0) { isc__nmsocket_detach(&sock); } -isc_result_t +void isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc_nm_cb_t cb, void *cbarg, unsigned int timeout, size_t extrahandlesize) { @@ -726,7 +725,6 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, isc__netievent_udpconnect_t *event = NULL; isc__nm_uvreq_t *req = NULL; sa_family_t sa_family; - uv_os_sock_t fd; REQUIRE(VALID_NM(mgr)); REQUIRE(local != NULL); @@ -734,15 +732,6 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, sa_family = peer->addr.type.sa.sa_family; - /* - * The socket() call can fail spuriously on FreeBSD 12, so we - * need to handle the failure early and gracefully. - */ - result = isc__nm_socket(sa_family, SOCK_DGRAM, 0, &fd); - if (result != ISC_R_SUCCESS) { - return (result); - } - sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t)); isc__nmsocket_init(sock, mgr, isc_nm_udpsocket, local); @@ -751,10 +740,27 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, sock->read_timeout = timeout; sock->extrahandlesize = extrahandlesize; sock->peer = peer->addr; - sock->fd = fd; sock->result = ISC_R_DEFAULT; atomic_init(&sock->client, true); + req = isc__nm_uvreq_get(mgr, sock); + req->cb.connect = cb; + req->cbarg = cbarg; + req->peer = peer->addr; + req->local = local->addr; + + result = isc__nm_socket(sa_family, SOCK_DGRAM, 0, &sock->fd); + if (result != ISC_R_SUCCESS) { + if (isc__nm_in_netthread()) { + sock->tid = isc_nm_tid(); + } + isc__nmsocket_clearcb(sock); + isc__nm_connectcb(sock, req, result, true); + atomic_store(&sock->closed, true); + isc__nmsocket_detach(&sock); + return; + } + result = isc__nm_socket_reuse(sock->fd); RUNTIME_CHECK(result == ISC_R_SUCCESS || result == ISC_R_NOTIMPLEMENTED); @@ -767,12 +773,6 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, (void)isc__nm_socket_dontfrag(sock->fd, sa_family); - req = isc__nm_uvreq_get(mgr, sock); - req->cb.connect = cb; - req->cbarg = cbarg; - req->peer = peer->addr; - req->local = local->addr; - event = isc__nm_get_netievent_udpconnect(mgr, sock, req); if (isc__nm_in_netthread()) { @@ -788,17 +788,12 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer, (isc__netievent_t *)event); } LOCK(&sock->lock); - result = sock->result; while (sock->result == ISC_R_DEFAULT) { WAIT(&sock->cond, &sock->lock); - result = sock->result; } atomic_store(&sock->active, true); BROADCAST(&sock->scond); UNLOCK(&sock->lock); - ENSURE(result != ISC_R_DEFAULT); - - return (result); } void diff --git a/lib/isc/tests/doh_test.c b/lib/isc/tests/doh_test.c index 9c22c11a0f..d27b1f7b9b 100644 --- a/lib/isc/tests/doh_test.c +++ b/lib/isc/tests/doh_test.c @@ -55,7 +55,7 @@ static uint64_t stop_magic = 0; static uv_buf_t send_msg = { .base = (char *)&send_magic, .len = sizeof(send_magic) }; -static atomic_uint_fast64_t nsends; +static atomic_int_fast64_t nsends; static atomic_uint_fast64_t ssends; static atomic_uint_fast64_t sreads; @@ -71,6 +71,8 @@ static bool reuse_supported = true; static atomic_bool POST = ATOMIC_VAR_INIT(true); +static atomic_bool slowdown = ATOMIC_VAR_INIT(false); + static atomic_bool use_TLS = ATOMIC_VAR_INIT(false); static isc_tlsctx_t *server_tlsctx = NULL; static isc_tlsctx_t *client_tlsctx = NULL; @@ -117,6 +119,7 @@ connect_send_cb(isc_nmhandle_t *handle, isc_result_t result, void *arg) { memmove(&data, arg, sizeof(data)); isc_mem_put(handle->sock->mgr->mctx, arg, sizeof(data)); if (result != ISC_R_SUCCESS) { + atomic_store(&slowdown, true); goto error; } @@ -135,11 +138,10 @@ error: data.region.length); } -static isc_result_t +static void connect_send_request(isc_nm_t *mgr, const char *uri, bool post, isc_region_t *region, isc_nm_recv_cb_t cb, void *cbarg, bool tls, unsigned int timeout) { - isc_result_t result; isc_region_t copy; csdata_t *data = NULL; isc_tlsctx_t *ctx = NULL; @@ -153,10 +155,8 @@ connect_send_request(isc_nm_t *mgr, const char *uri, bool post, ctx = client_tlsctx; } - result = isc_nm_httpconnect( - mgr, NULL, (isc_nmiface_t *)&tcp_listen_addr, uri, post, - connect_send_cb, data, ctx, timeout, 0); - return (result); + isc_nm_httpconnect(mgr, NULL, (isc_nmiface_t *)&tcp_listen_addr, uri, + post, connect_send_cb, data, ctx, timeout, 0); } static int @@ -372,28 +372,18 @@ sockaddr_to_url(isc_sockaddr_t *sa, const bool https, char *outbuf, static void doh_receive_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, void *cbarg) { - uint_fast64_t sends = atomic_load(&nsends); assert_non_null(handle); UNUSED(cbarg); UNUSED(region); + (void)atomic_fetch_sub(&nsends, 1); + if (eresult == ISC_R_SUCCESS) { atomic_fetch_add(&csends, 1); atomic_fetch_add(&creads, 1); - if (sends > 0) { - atomic_fetch_sub(&nsends, 1); - } isc_nm_resumeread(handle); } else { /* We failed to connect; try again */ - while (sends > 0) { - /* Continue until we subtract or we are done */ - if (atomic_compare_exchange_weak(&nsends, &sends, - sends - 1)) { - sends--; - break; - } - } atomic_store(&was_error, true); } } @@ -486,11 +476,10 @@ doh_noop(void **state) { sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), DOH_PATH); - (void)connect_send_request( - connect_nm, req_url, atomic_load(&POST), - &(isc_region_t){ .base = (uint8_t *)send_msg.base, - .length = send_msg.len }, - noop_read_cb, NULL, atomic_load(&use_TLS), 30000); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); isc_nm_closedown(connect_nm); @@ -531,11 +520,10 @@ doh_noresponse(void **state) { sockaddr_to_url(&tcp_listen_addr, false, req_url, sizeof(req_url), DOH_PATH); - (void)connect_send_request( - connect_nm, req_url, atomic_load(&POST), - &(isc_region_t){ .base = (uint8_t *)send_msg.base, - .length = send_msg.len }, - noop_read_cb, NULL, atomic_load(&use_TLS), 30000); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + noop_read_cb, NULL, atomic_load(&use_TLS), 30000); isc_nm_stoplistening(listen_sock); isc_nmsocket_close(&listen_sock); @@ -558,7 +546,7 @@ doh_noresponse_GET(void **state) { static void doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region, void *cbarg) { - uint_fast64_t sends = atomic_load(&nsends); + int_fast64_t sends = atomic_fetch_sub(&nsends, 1); assert_non_null(handle); UNUSED(region); @@ -567,7 +555,6 @@ doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, atomic_fetch_add(&creads, 1); if (sends > 0) { size_t i; - atomic_fetch_sub(&nsends, 1); for (i = 0; i < NWRITES / 2; i++) { eresult = isc__nm_http_request( handle, @@ -579,15 +566,6 @@ doh_receive_send_reply_cb(isc_nmhandle_t *handle, isc_result_t eresult, } } } else { - /* We failed to connect; try again */ - while (sends > 0) { - /* Continue until we subtract or we are done */ - if (atomic_compare_exchange_weak(&nsends, &sends, - sends - 1)) { - sends--; - break; - } - } atomic_store(&was_error, true); } } @@ -596,25 +574,27 @@ static isc_threadresult_t doh_connect_thread(isc_threadarg_t arg) { isc_nm_t *connect_nm = (isc_nm_t *)arg; char req_url[256]; - isc_result_t result; + int64_t sends = atomic_load(&nsends); sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, sizeof(req_url), DOH_PATH); - while (atomic_load(&nsends) > 0) { - result = connect_send_request( + while (sends > 0) { + /* + * We need to back off and slow down if we start getting + * errors, to prevent a thundering herd problem. + */ + if (atomic_load(&slowdown)) { + usleep(1000 * workers); + atomic_store(&slowdown, false); + } + connect_send_request( connect_nm, req_url, atomic_load(&POST), &(isc_region_t){ .base = (uint8_t *)send_msg.base, .length = send_msg.len }, doh_receive_send_reply_cb, NULL, atomic_load(&use_TLS), 30000); - /* protection against "too many open files" */ -#ifndef _WIN32 - if (result != ISC_R_SUCCESS) { - INSIST(result == ISC_R_TOOMANYOPENFILES); - usleep(1000 * workers); - } -#endif + sends = atomic_load(&nsends); } return ((isc_threadresult_t)0); @@ -642,13 +622,11 @@ doh_recv_one(void **state) { sockaddr_to_url(&tcp_listen_addr, atomic_load(&use_TLS), req_url, sizeof(req_url), DOH_PATH); - result = connect_send_request( - connect_nm, req_url, atomic_load(&POST), - &(isc_region_t){ .base = (uint8_t *)send_msg.base, - .length = send_msg.len }, - doh_receive_reply_cb, NULL, atomic_load(&use_TLS), 30000); - - assert_int_equal(result, ISC_R_SUCCESS); + connect_send_request(connect_nm, req_url, atomic_load(&POST), + &(isc_region_t){ .base = (uint8_t *)send_msg.base, + .length = send_msg.len }, + doh_receive_reply_cb, NULL, atomic_load(&use_TLS), + 30000); while (atomic_load(&nsends) > 0) { if (atomic_load(&was_error)) { @@ -766,12 +744,10 @@ doh_recv_two(void **state) { ctx = client_tlsctx; } - result = isc_nm_httpconnect( - connect_nm, NULL, (isc_nmiface_t *)&tcp_listen_addr, req_url, - atomic_load(&POST), doh_connect_send_two_requests_cb, NULL, ctx, - 5000, 0); - - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_httpconnect(connect_nm, NULL, (isc_nmiface_t *)&tcp_listen_addr, + req_url, atomic_load(&POST), + doh_connect_send_two_requests_cb, NULL, ctx, 5000, + 0); while (atomic_load(&nsends) > 0) { if (atomic_load(&was_error)) { diff --git a/lib/isc/tests/netmgr_test.c b/lib/isc/tests/netmgr_test.c index c52bf11c32..631001e408 100644 --- a/lib/isc/tests/netmgr_test.c +++ b/lib/isc/tests/netmgr_test.c @@ -456,12 +456,15 @@ unref: static void connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { isc_nmhandle_t *readhandle = NULL; + UNUSED(cbarg); F(); + isc_refcount_decrement(&active_cconnects); + if (eresult != ISC_R_SUCCESS) { - goto unref; + return; } atomic_fetch_add(&cconnects, 1); @@ -471,9 +474,6 @@ connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { isc_nm_read(handle, connect_read_cb, NULL); connect_send(handle); - -unref: - isc_refcount_decrement(&active_cconnects); } static void @@ -564,40 +564,27 @@ stream_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { return (ISC_R_SUCCESS); } -typedef isc_result_t (*connect_func)(isc_nm_t *); +typedef void (*connect_func)(isc_nm_t *); static isc_threadresult_t connect_thread(isc_threadarg_t arg) { connect_func connect = (connect_func)arg; - isc_result_t result; isc_sockaddr_t connect_addr; connect_addr = (isc_sockaddr_t){ .length = 0 }; isc_sockaddr_fromin6(&connect_addr, &in6addr_loopback, 0); while (atomic_load(&do_send)) { - uint_fast32_t active = - isc_refcount_increment0(&active_cconnects); - if (active >= workers) { + uint_fast32_t active = isc_refcount_current(&active_cconnects); + if (active > workers) { /* - * If we have more active connections than workers start - * slowing down the connections to prevent the + * If we have more active connections than workers, + * start slowing down the connections to prevent the * thundering herd problem. */ usleep((active - workers) * 1000); } - result = connect(connect_nm); - if (result != ISC_R_SUCCESS) { - /* - * Also back-off and slow down if we start getting - * errors to prevent the thundering herd problem. This - * could especially happen on FreeBSD where socket() - * call can fail because of system limits and in such - * case it's not such good idea to try again quickly. - */ - isc_refcount_decrement(&active_cconnects); - usleep(1000); - } + connect(connect_nm); } return ((isc_threadresult_t)0); @@ -605,11 +592,12 @@ connect_thread(isc_threadarg_t arg) { /* UDP */ -static isc_result_t +static void udp_connect(isc_nm_t *nm) { - return (isc_nm_udpconnect(nm, (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, - connect_connect_cb, NULL, T_CONNECT, 0)); + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); } static void @@ -659,20 +647,12 @@ mock_listenudp_uv_udp_recv_start(void **state __attribute__((unused))) { static void mock_udpconnect_uv_udp_open(void **state __attribute__((unused))) { - isc_result_t result = ISC_R_SUCCESS; - WILL_RETURN(uv_udp_open, UV_ENOMEM); isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect(connect_nm, - (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, - noop_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - assert_int_not_equal(result, ISC_R_SUCCESS); - + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0); isc_nm_closedown(connect_nm); RESET_RETURN; @@ -680,20 +660,12 @@ mock_udpconnect_uv_udp_open(void **state __attribute__((unused))) { static void mock_udpconnect_uv_udp_bind(void **state __attribute__((unused))) { - isc_result_t result = ISC_R_SUCCESS; - WILL_RETURN(uv_udp_bind, UV_ENOMEM); isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect(connect_nm, - (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, - noop_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - assert_int_not_equal(result, ISC_R_SUCCESS); - + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0); isc_nm_closedown(connect_nm); RESET_RETURN; @@ -702,20 +674,12 @@ mock_udpconnect_uv_udp_bind(void **state __attribute__((unused))) { #if HAVE_UV_UDP_CONNECT static void mock_udpconnect_uv_udp_connect(void **state __attribute__((unused))) { - isc_result_t result = ISC_R_SUCCESS; - WILL_RETURN(uv_udp_connect, UV_ENOMEM); isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect(connect_nm, - (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, - noop_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - assert_int_not_equal(result, ISC_R_SUCCESS); - + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0); isc_nm_closedown(connect_nm); RESET_RETURN; @@ -724,20 +688,12 @@ mock_udpconnect_uv_udp_connect(void **state __attribute__((unused))) { static void mock_udpconnect_uv_recv_buffer_size(void **state __attribute__((unused))) { - isc_result_t result = ISC_R_SUCCESS; - WILL_RETURN(uv_recv_buffer_size, UV_ENOMEM); isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect(connect_nm, - (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, - noop_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - assert_int_equal(result, ISC_R_SUCCESS); /* FIXME: should fail */ - + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0); isc_nm_closedown(connect_nm); RESET_RETURN; @@ -745,20 +701,12 @@ mock_udpconnect_uv_recv_buffer_size(void **state __attribute__((unused))) { static void mock_udpconnect_uv_send_buffer_size(void **state __attribute__((unused))) { - isc_result_t result = ISC_R_SUCCESS; - WILL_RETURN(uv_send_buffer_size, UV_ENOMEM); isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect(connect_nm, - (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, - noop_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - assert_int_equal(result, ISC_R_SUCCESS); /* FIXME: should fail */ - + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0); isc_nm_closedown(connect_nm); RESET_RETURN; @@ -777,17 +725,10 @@ udp_noop(void **state __attribute__((unused))) { isc_nmsocket_close(&listen_sock); assert_null(listen_sock); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect(connect_nm, - (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, - noop_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); - + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0); isc_nm_closedown(connect_nm); atomic_assert_int_eq(cconnects, 0); @@ -806,16 +747,10 @@ udp_noresponse(void **state __attribute__((unused))) { noop_recv_cb, NULL, 0, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect( - connect_nm, (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_EQ(csends, 1); @@ -849,16 +784,10 @@ udp_recv_one(void **state __attribute__((unused))) { listen_read_cb, NULL, 0, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect( - connect_nm, (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_LE(nsends, 0); @@ -896,29 +825,17 @@ udp_recv_two(void **state __attribute__((unused))) { listen_read_cb, NULL, 0, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect( - connect_nm, (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_udpconnect( - connect_nm, (isc_nmiface_t *)&udp_connect_addr, - (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_udpconnect(connect_nm, (isc_nmiface_t *)&udp_connect_addr, + (isc_nmiface_t *)&udp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 2); WAIT_FOR_LE(nsends, 0); @@ -1135,11 +1052,12 @@ udp_half_recv_half_send(void **state __attribute__((unused))) { static isc_quota_t * tcp_listener_init_quota(size_t nthreads); -static isc_result_t +static void tcp_connect(isc_nm_t *nm) { - return (isc_nm_tcpconnect(nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - connect_connect_cb, NULL, 1, 0)); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpconnect(nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, + NULL, 1, 0); } static void @@ -1156,17 +1074,10 @@ tcp_noop(void **state __attribute__((unused))) { isc_nmsocket_close(&listen_sock); assert_null(listen_sock); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpconnect(connect_nm, - (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - noop_connect_cb, NULL, 1, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); - + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, noop_connect_cb, + NULL, 1, 0); isc_nm_closedown(connect_nm); atomic_assert_int_eq(cconnects, 0); @@ -1186,16 +1097,10 @@ tcp_noresponse(void **state __attribute__((unused))) { &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpconnect(connect_nm, - (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - connect_connect_cb, NULL, 1, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, + NULL, 1, 0); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_EQ(csends, 1); @@ -1231,16 +1136,10 @@ tcp_recv_one(void **state __attribute__((unused))) { &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_LE(nsends, 0); @@ -1280,29 +1179,17 @@ tcp_recv_two(void **state __attribute__((unused))) { &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, + NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 2); WAIT_FOR_LE(nsends, 0); @@ -1532,7 +1419,7 @@ tcp_listener_init_quota(size_t nthreads) { isc_quota_max(&listener_quota, max_quota); quotap = &listener_quota; } - return quotap; + return (quotap); } static void @@ -1577,11 +1464,12 @@ tcp_half_recv_half_send_quota(void **state) { /* TCPDNS */ -static isc_result_t +static void tcpdns_connect(isc_nm_t *nm) { - return (isc_nm_tcpdnsconnect(nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - connect_connect_cb, NULL, T_CONNECT, 0)); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); } static void @@ -1599,15 +1487,9 @@ tcpdns_noop(void **state __attribute__((unused))) { assert_null(listen_sock); isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpdnsconnect(connect_nm, - (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - noop_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - usleep(1000); - } - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_tcpdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0); isc_nm_closedown(connect_nm); atomic_assert_int_eq(cconnects, 0); @@ -1632,11 +1514,9 @@ tcpdns_noresponse(void **state __attribute__((unused))) { } assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_tcpdnsconnect(connect_nm, - (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - connect_connect_cb, NULL, T_CONNECT, 0); - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_tcpdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_EQ(csends, 1); @@ -1672,14 +1552,9 @@ tcpdns_recv_one(void **state __attribute__((unused))) { assert_int_equal(result, ISC_R_SUCCESS); isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpdnsconnect(connect_nm, - (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - connect_connect_cb, NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_tcpdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_LE(nsends, 0); @@ -1718,31 +1593,17 @@ tcpdns_recv_two(void **state __attribute__((unused))) { NULL, listen_accept_cb, NULL, 0, 0, NULL, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpdnsconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); - assert_int_equal(result, ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 1); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tcpdnsconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - } - } while (result != ISC_R_SUCCESS); - assert_int_equal(result, ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tcpdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0); WAIT_FOR_EQ(cconnects, 2); @@ -1961,12 +1822,13 @@ tcpdns_half_recv_half_send(void **state __attribute__((unused))) { /* TLSDNS */ -static isc_result_t +static void tlsdns_connect(isc_nm_t *nm) { - return (isc_nm_tlsdnsconnect(nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, - connect_connect_cb, NULL, T_CONNECT, 0, - tcp_connect_tlsctx)); + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx); } static void @@ -1984,17 +1846,10 @@ tlsdns_noop(void **state __attribute__((unused))) { isc_nmsocket_close(&listen_sock); assert_null(listen_sock); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tlsdnsconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, noop_connect_cb, - NULL, T_CONNECT, 0, tcp_connect_tlsctx); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - usleep(1000); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, noop_connect_cb, + NULL, T_CONNECT, 0, tcp_connect_tlsctx); isc_nm_closedown(connect_nm); @@ -2020,17 +1875,11 @@ tlsdns_noresponse(void **state __attribute__((unused))) { &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - do { - isc_refcount_increment0(&active_cconnects); - result = isc_nm_tlsdnsconnect( - connect_nm, (isc_nmiface_t *)&connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, - NULL, T_CONNECT, 0, tcp_connect_tlsctx); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - usleep(1000); - } - } while (result != ISC_R_SUCCESS); + isc_refcount_increment0(&active_cconnects); + isc_nm_tlsdnsconnect(connect_nm, (isc_nmiface_t *)&connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_EQ(csends, 1); @@ -2067,15 +1916,10 @@ tlsdns_recv_one(void **state __attribute__((unused))) { assert_int_equal(result, ISC_R_SUCCESS); isc_refcount_increment0(&active_cconnects); - result = isc_nm_tlsdnsconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, NULL, - T_CONNECT, 0, tcp_connect_tlsctx); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - usleep(1000); - } - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_tlsdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx); WAIT_FOR_EQ(cconnects, 1); WAIT_FOR_LE(nsends, 0); @@ -2116,28 +1960,18 @@ tlsdns_recv_two(void **state __attribute__((unused))) { assert_int_equal(result, ISC_R_SUCCESS); isc_refcount_increment0(&active_cconnects); - result = isc_nm_tlsdnsconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, NULL, - T_CONNECT, 0, tcp_connect_tlsctx); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - usleep(1000); - } - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_tlsdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx); WAIT_FOR_EQ(cconnects, 1); isc_refcount_increment0(&active_cconnects); - result = isc_nm_tlsdnsconnect( - connect_nm, (isc_nmiface_t *)&tcp_connect_addr, - (isc_nmiface_t *)&tcp_listen_addr, connect_connect_cb, NULL, - T_CONNECT, 0, tcp_connect_tlsctx); - if (result != ISC_R_SUCCESS) { - isc_refcount_decrement(&active_cconnects); - usleep(1000); - } - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_tlsdnsconnect(connect_nm, (isc_nmiface_t *)&tcp_connect_addr, + (isc_nmiface_t *)&tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, 0, + tcp_connect_tlsctx); WAIT_FOR_EQ(cconnects, 2); diff --git a/lib/isc/tests/tls_test.c b/lib/isc/tests/tls_test.c index 3bfff77719..9aaa899bcd 100644 --- a/lib/isc/tests/tls_test.c +++ b/lib/isc/tests/tls_test.c @@ -66,6 +66,8 @@ static atomic_uint_fast64_t csends; static atomic_uint_fast64_t creads; static atomic_uint_fast64_t ctimeouts; +static atomic_bool slowdown = ATOMIC_VAR_INIT(false); + static unsigned int workers = 0; static bool reuse_supported = true; @@ -389,6 +391,7 @@ tls_connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, if (eresult != ISC_R_SUCCESS) { uint_fast64_t sends = atomic_load(&nsends); + atomic_store(&slowdown, true); /* We failed to connect; try again */ while (sends > 0) { @@ -431,10 +434,9 @@ tls_noop(void **state) { isc_nmsocket_close(&listen_sock); assert_null(listen_sock); - (void)isc_nm_tlsconnect(connect_nm, (isc_nmiface_t *)&tls_connect_addr, - (isc_nmiface_t *)&tls_listen_addr, - noop_connect_cb, NULL, client_tlsctx, 1, 0); - + isc_nm_tlsconnect(connect_nm, (isc_nmiface_t *)&tls_connect_addr, + (isc_nmiface_t *)&tls_listen_addr, noop_connect_cb, + NULL, client_tlsctx, 1, 0); isc_nm_closedown(connect_nm); assert_int_equal(0, atomic_load(&cconnects)); @@ -462,10 +464,9 @@ tls_noresponse(void **state) { server_tlsctx, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - (void)isc_nm_tlsconnect(connect_nm, (isc_nmiface_t *)&tls_connect_addr, - (isc_nmiface_t *)&tls_listen_addr, - noop_connect_cb, NULL, client_tlsctx, 1, 0); - + isc_nm_tlsconnect(connect_nm, (isc_nmiface_t *)&tls_connect_addr, + (isc_nmiface_t *)&tls_listen_addr, noop_connect_cb, + NULL, client_tlsctx, 1, 0); isc_nm_stoplistening(listen_sock); isc_nmsocket_close(&listen_sock); assert_null(listen_sock); @@ -479,21 +480,23 @@ static isc_threadresult_t tls_connect_thread(isc_threadarg_t arg) { isc_nm_t *connect_nm = (isc_nm_t *)arg; isc_sockaddr_t tls_connect_addr; - isc_result_t result; tls_connect_addr = (isc_sockaddr_t){ .length = 0 }; isc_sockaddr_fromin6(&tls_connect_addr, &in6addr_loopback, 0); while (atomic_load(&nsends) > 0) { - result = isc_nm_tlsconnect( + /* + * We need to back off and slow down if we start getting + * errors, to prevent a thundering herd problem. + */ + if (atomic_load(&slowdown)) { + usleep(1000 * workers); + atomic_store(&slowdown, false); + } + isc_nm_tlsconnect( connect_nm, (isc_nmiface_t *)&tls_connect_addr, (isc_nmiface_t *)&tls_listen_addr, tls_connect_connect_cb, NULL, client_tlsctx, 1, 0); - /* protection against "too many open files" */ - if (result != ISC_R_SUCCESS) { - atomic_fetch_sub(&nsends, 1); - usleep(1000 * workers); - } } return ((isc_threadresult_t)0); @@ -518,10 +521,9 @@ tls_recv_one(void **state) { server_tlsctx, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - (void)isc_nm_tlsconnect(connect_nm, (isc_nmiface_t *)&tls_connect_addr, - (isc_nmiface_t *)&tls_listen_addr, - tls_connect_connect_cb, NULL, client_tlsctx, - 1000, 0); + isc_nm_tlsconnect(connect_nm, (isc_nmiface_t *)&tls_connect_addr, + (isc_nmiface_t *)&tls_listen_addr, + tls_connect_connect_cb, NULL, client_tlsctx, 1000, 0); while (atomic_load(&nsends) > 0) { isc_thread_yield(); @@ -573,11 +575,10 @@ tls_recv_two(void **state) { server_tlsctx, &listen_sock); assert_int_equal(result, ISC_R_SUCCESS); - result = isc_nm_tlsconnect( - connect_nm, (isc_nmiface_t *)&tls_connect_addr, - (isc_nmiface_t *)&tls_listen_addr, tls_connect_connect_cb, NULL, - client_tlsctx, 100000, 0); - assert_int_equal(result, ISC_R_SUCCESS); + isc_nm_tlsconnect(connect_nm, (isc_nmiface_t *)&tls_connect_addr, + (isc_nmiface_t *)&tls_listen_addr, + tls_connect_connect_cb, NULL, client_tlsctx, 100000, + 0); while (atomic_load(&nsends) > 0) { isc_thread_yield(); diff --git a/lib/isc/tests/uv_wrap.h b/lib/isc/tests/uv_wrap.h index b1b0e3369f..46d41d2d45 100644 --- a/lib/isc/tests/uv_wrap.h +++ b/lib/isc/tests/uv_wrap.h @@ -111,7 +111,9 @@ __wrap_uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr, return (atomic_load(&__state_uv_udp_bind)); } -static atomic_int __state_uv_udp_connect = ATOMIC_VAR_INIT(0); +static atomic_int __state_uv_udp_connect + __attribute__((unused)) = ATOMIC_VAR_INIT(0); + #if HAVE_UV_UDP_CONNECT int __wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr) { @@ -122,7 +124,9 @@ __wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr) { } #endif /* HAVE_UV_UDP_CONNECT */ -static atomic_int __state_uv_udp_getpeername = ATOMIC_VAR_INIT(0); +static atomic_int __state_uv_udp_getpeername + __attribute__((unused)) = ATOMIC_VAR_INIT(0); + #if HAVE_UV_UDP_CONNECT int __wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name,