]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
isc_nm_*connect() always return via callback
authorOndřej Surý <ondrej@sury.org>
Wed, 31 Mar 2021 16:32:32 +0000 (18:32 +0200)
committerOndřej Surý <ondrej@sury.org>
Wed, 7 Apr 2021 13:36:59 +0000 (15:36 +0200)
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.

15 files changed:
bin/rndc/rndc.c
bin/tests/test_client.c
lib/dns/xfrin.c
lib/isc/include/isc/netmgr.h
lib/isc/netmgr/http.c
lib/isc/netmgr/netmgr.c
lib/isc/netmgr/tcp.c
lib/isc/netmgr/tcpdns.c
lib/isc/netmgr/tlsdns.c
lib/isc/netmgr/tlsstream.c
lib/isc/netmgr/udp.c
lib/isc/tests/doh_test.c
lib/isc/tests/netmgr_test.c
lib/isc/tests/tls_test.c
lib/isc/tests/uv_wrap.h

index bc3d1243285dad909ab01aa7ffd6c0c2cb4c8982..47c862e24f1a8743b0ffb411cb60fa1e6ca106f2 100644 (file)
@@ -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
index 4056e537f33c99a793347e0935ecfe76d24d7c7d..c145115af8aff278d4e4acd40eda47141bef0395 100644 (file)
@@ -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();
 
index c0e06cf71a12ec19699d7daef66a23ed993ac4b2..03ccb115a2c70f92d2af8bead8f7c53bad9b7ea8 100644 (file)
@@ -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);
index 215b0150b023a883b460838ecab28d99e89fa73d..a89436345f06a6b236485f23d1986d6981a37873 100644 (file)
@@ -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,
index 51e7096ec171a433dea761e39945e23a2013a2cb..f1595eee944d8e60a062115db68c38d582886021 100644 (file)
@@ -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
index 64b51aa9be84ce356fc00a15a1746494c1769023..407637081f0a1f32ca8d69a7d3221be6038636da 100644 (file)
@@ -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
index dc25b9800ddfe7db51dc0077ad6b94e16738ce40..4c5e45167c8061715acabf4def636626104fd65f 100644 (file)
@@ -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
index dbdb21332db07987f5d3e682c05bb3d27d32817d..b2dba833ed5e097b6f9839a1705f816c8f226b11 100644 (file)
@@ -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
index c7aba2cd35038aa1eebe8177101ca971250a0827..fe437bf83bb1235e566d9f7a7da9d5988db4c25b 100644 (file)
@@ -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
index bf9c5f9ce5cd739760e908cee899bc64d14a08b5..27a6bfcadb7e6d03d4e05434f0d9b706404d2bb1 100644 (file)
@@ -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:
index 9485fb76d5152e4e18bfc8572d5e51f748aa6ca5..02981f2723682db922a2faef3c29cc0d485d9456 100644 (file)
@@ -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
index 9c22c11a0fd4165ef31e4b95d36703d5cfc951fd..d27b1f7b9bfb59cf38225bb074042cc5fb634468 100644 (file)
@@ -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)) {
index c52bf11c32274b16393f1e96016011849eb494ed..631001e408924da93a34b474756c44bfa1692ffe 100644 (file)
@@ -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);
 
index 3bfff777191fc1cd99e035f7ee1aa28b8ff9f8a5..9aaa899bcd7ef4adab7efee542060ecd20ec1cec 100644 (file)
@@ -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();
index b1b0e3369fe275a67dd467b560a59b6142c77fa0..46d41d2d454c8e2a8c7ebe1de929cb6f85ffba8b 100644 (file)
@@ -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,