diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 177adec3c6..f309ab5131 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -603,6 +603,13 @@ isc__nmsocket_prep_destroy(isc_nmsocket_t *sock); * if there are no remaining references or active handles. */ +bool +isc__nmsocket_active(isc_nmsocket_t *sock); +/*%< + * Check is socket 'sock' is active - by checking either sock->active or + * sock->parent->active; + */ + void isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ev0); /*%< diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 6a66bd5fdb..7943b1f5ba 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -681,7 +681,7 @@ isc__nm_enqueue_ievent(isc__networker_t *worker, isc__netievent_t *event) { uv_async_send(&worker->async); } -static bool +bool isc__nmsocket_active(isc_nmsocket_t *sock) { REQUIRE(VALID_NMSOCK(sock)); if (sock->parent != NULL) { diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 6b79d8e0bc..0bad9ceaf5 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -179,14 +179,18 @@ stop_udp_child(isc_nmsocket_t *sock) { static void stoplistening(isc_nmsocket_t *sock) { + INSIST(sock->type == isc_nm_udplistener); /* * Socket is already closing; there's nothing to do. */ - if (uv_is_closing((uv_handle_t *) &sock->uv_handle.udp)) { + if (!isc__nmsocket_active(sock)) { return; } - - INSIST(sock->type == isc_nm_udplistener); + /* + * Mark it inactive now so that all sends will be ignored + * and we won't try to stop listening again. + */ + atomic_store(&sock->active, false); for (int i = 0; i < sock->nchildren; i++) { isc__netievent_udpstop_t *event = NULL; @@ -375,6 +379,11 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, return (ISC_R_UNEXPECTED); } + if (!isc__nmsocket_active(sock)) { + isc_nmhandle_unref(handle); + return (ISC_R_CANCELED); + } + if (isc__nm_in_netthread()) { ntid = isc_nm_tid(); } else { @@ -425,7 +434,7 @@ isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0) { REQUIRE(worker->id == ievent->sock->tid); - if (atomic_load(&ievent->sock->active)) { + if (isc__nmsocket_active(ievent->sock)) { udp_send_direct(ievent->sock, ievent->req, &ievent->peer); } else { ievent->req->cb.send(ievent->req->handle,