From: Witold Kręcicki Date: Fri, 22 Nov 2019 13:13:19 +0000 (+0100) Subject: netmgr: actively close all sockets when shutting down server X-Git-Tag: v9.15.7~75^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d6c5052f7e48971c537cdfc985fcbc8ba7a95de6;p=thirdparty%2Fbind9.git netmgr: actively close all sockets when shutting down server without this change, named could sometimes lag for a while on shutdown while it waited for open TCP connections to time out. --- diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 0844cdcbb7d..f2aa88af1a3 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -116,12 +116,9 @@ typedef enum isc__netievent_type { netievent_tcpstoplisten, netievent_tcpclose, netievent_closecb, + netievent_shutdown, } isc__netievent_type; -typedef struct isc__netievent_stop { - isc__netievent_type type; -} isc__netievent_stop_t; - /* * We have to split it because we can read and write on a socket * simultaneously. @@ -209,10 +206,13 @@ typedef struct isc__netievent { isc__netievent_type type; } isc__netievent_t; +typedef isc__netievent_t isc__netievent_shutdown_t; +typedef isc__netievent_t isc__netievent_stop_t; + typedef union { isc__netievent_t ni; - isc__netievent_stop_t nis; - isc__netievent_udplisten_t niul; + isc__netievent__socket_t nis; + isc__netievent__socket_req_t nisr; isc__netievent_udpsend_t nius; } isc__netievent_storage_t; @@ -523,6 +523,13 @@ isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ievent0); * Issue a 'handle closed' callback on the socket. */ +void +isc__nm_async_shutdown(isc__networker_t *worker, isc__netievent_t *ievent0); +/*%< + * Walk through all uv handles, get the underlying sockets and issue + * close on them. + */ + isc_result_t isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb, void *cbarg); @@ -555,6 +562,12 @@ isc__nm_tcp_close(isc_nmsocket_t *sock); * Close a TCP socket. */ +void +isc__nm_tcp_shutdown(isc_nmsocket_t *sock); +/*%< + * Called on shutdown to close and clean up a listening TCP socket. + */ + void isc__nm_async_tcpconnect(isc__networker_t *worker, isc__netievent_t *ievent0); void diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index d7699e6d97e..2b02a54734d 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -309,6 +309,12 @@ isc_nm_destroy(isc_nm_t **mgr0) { mgr = *mgr0; *mgr0 = NULL; + for (size_t i = 0; i < mgr->nworkers; i++) { + isc__netievent_t *event = NULL; + event = isc__nm_get_ievent(mgr, netievent_shutdown); + isc__nm_enqueue_ievent(&mgr->workers[i], event); + } + /* * Wait for the manager to be dereferenced elsehwere. */ @@ -512,6 +518,9 @@ async_cb(uv_async_t *handle) { case netievent_closecb: isc__nm_async_closecb(worker, ievent); break; + case netievent_shutdown: + isc__nm_async_shutdown(worker, ievent); + break; default: INSIST(0); ISC_UNREACHABLE(); @@ -1174,6 +1183,27 @@ isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ievent0) { isc_nmsocket_detach(&ievent->sock); } +static void +shutdown_walk_cb(uv_handle_t *handle, void *arg) { + isc_nmsocket_t *sock = NULL; + + UNUSED(arg); + + switch(handle->type) { + case UV_TCP: + isc__nm_tcp_shutdown((isc_nmsocket_t *) handle->data); + break; + default: + break; + } +} + +void +isc__nm_async_shutdown(isc__networker_t *worker, isc__netievent_t *ievent0) { + UNUSED(ievent0); + uv_walk(&worker->loop, shutdown_walk_cb, NULL); +} + bool isc__nm_acquire_interlocked(isc_nm_t *mgr) { LOCK(&mgr->lock); diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 5283740f5eb..bfe4af956d3 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -688,3 +688,10 @@ isc__nm_async_tcpclose(isc__networker_t *worker, isc__netievent_t *ievent0) { tcp_close_direct(ievent->sock); } + +void +isc__nm_tcp_shutdown(isc_nmsocket_t *sock) { + REQUIRE(VALID_NMSOCK(sock)); + + sock->rcb.recv(sock->tcphandle, NULL, sock->rcbarg); +}