]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Call the isc__nm_udp_send() callbacks asynchronously on shutdown
authorOndřej Surý <ondrej@isc.org>
Tue, 27 Sep 2022 13:20:33 +0000 (15:20 +0200)
committerOndřej Surý <ondrej@isc.org>
Thu, 29 Sep 2022 09:06:58 +0000 (11:06 +0200)
The isc__nm_udp_send() callback would be called synchronously when
shutting down or when the socket has been closed.  This could lead to
double locking in the calling code and thus those callbacks needs to be
called asynchronously.

lib/isc/netmgr/udp.c

index 9b715d9b6ce901ed8d9aabd5d940fd5f2f01cf15..587e368203d42fd18b3d04e46a5e67cf81bdd43a 100644 (file)
@@ -685,6 +685,7 @@ isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
        isc__networker_t *worker = NULL;
        uint32_t maxudp;
        int r;
+       isc_result_t result;
 
        REQUIRE(VALID_NMSOCK(sock));
        REQUIRE(sock->type == isc_nm_udpsocket);
@@ -706,16 +707,6 @@ isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
                return;
        }
 
-       if (isc__nm_closing(worker)) {
-               cb(handle, ISC_R_SHUTTINGDOWN, cbarg);
-               return;
-       }
-
-       if (isc__nmsocket_closing(sock)) {
-               cb(handle, ISC_R_CANCELED, cbarg);
-               return;
-       }
-
        uvreq = isc__nm_uvreq_get(sock->worker, sock);
        uvreq->uvbuf.base = (char *)region->base;
        uvreq->uvbuf.len = region->length;
@@ -725,6 +716,16 @@ isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
        uvreq->cb.send = cb;
        uvreq->cbarg = cbarg;
 
+       if (isc__nm_closing(worker)) {
+               result = ISC_R_SHUTTINGDOWN;
+               goto fail;
+       }
+
+       if (isc__nmsocket_closing(sock)) {
+               result = ISC_R_CANCELED;
+               goto fail;
+       }
+
        /*
         * We used uv_udp_connect(), so the peer address has to be
         * set to NULL or else uv_udp_send() could fail or assert,
@@ -738,8 +739,12 @@ isc__nm_udp_send(isc_nmhandle_t *handle, const isc_region_t *region,
                        &uvreq->uvbuf, 1, sa, udp_send_cb);
        if (r < 0) {
                isc__nm_incstats(sock, STATID_SENDFAIL);
-               isc__nm_failed_send_cb(sock, uvreq, isc_uverr2result(r));
+               result = isc_uverr2result(r);
+               goto fail;
        }
+       return;
+fail:
+       isc__nm_failed_send_cb(sock, uvreq, result);
 }
 
 static isc_result_t