Merge branch '3534-make-the-isc_nm_udp_send-on-shutdown-callback-asynchronous' into 'main'

Call the isc__nm_udp_send() callbacks asynchronously on shutdown

Closes #3534

See merge request isc-projects/bind9!6828
This commit is contained in:
Ondřej Surý 2022-09-29 10:04:40 +00:00
commit 05d60071a7
2 changed files with 26 additions and 11 deletions

View file

@ -104,3 +104,13 @@ functions MUST be called from the thread that created the network manager
socket.
The ``isc_nm_listen*()`` functions MUST be called from the ``main`` loop.
The general design of Network Manager is based on callbacks. An extra care must
be taken when implementing new functions because the callbacks MUST be called
asynchronously because the caller might be inside a lock and the same lock must
be acquired in the callback. This doesn't mean that the callback must be always
called asynchronously, because sometimes we are already in the libuv callback
and thus we can just call the callback directly, but in other places, especially
when returning an error, the control hasn't been returned to the caller yet and
in such case, the callback must be scheduled onto the event loop instead of
executing it directly.

View 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