From: Witold Kręcicki Date: Thu, 16 Jan 2020 11:13:28 +0000 (+0100) Subject: netmgr: fix a non-thread-safe access to libuv structures X-Git-Tag: v9.16.0~60^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f75a9e32be18788bec50d714f76f538dfe366b19;p=thirdparty%2Fbind9.git netmgr: fix a non-thread-safe access to libuv structures In tcp and udp stoplistening code we accessed libuv structures from a different thread, which caused a shutdown crash when named was under load. Also added additional DbC checks making sure we're in a proper thread when accessing uv_ functions. --- diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index f309ab51318..7dfa8872e64 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -606,8 +606,8 @@ isc__nmsocket_prep_destroy(isc_nmsocket_t *sock); bool isc__nmsocket_active(isc_nmsocket_t *sock); /*%< - * Check is socket 'sock' is active - by checking either sock->active or - * sock->parent->active; + * Determine whether 'sock' is active by checking 'sock->active' + * or, for child sockets, 'sock->parent->active'. */ void diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 17a97cda383..e0c566e176c 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -419,7 +419,7 @@ stoplistening(isc_nmsocket_t *sock) { event = isc__nm_get_ievent(sock->mgr, netievent_tcpchildstop); isc_nmsocket_attach(&sock->children[i], &event->sock); - if (i == sock->tid) { + if (isc_nm_tid() == sock->children[i].tid) { isc__nm_async_tcpchildstop(&sock->mgr->workers[i], (isc__netievent_t *) event); isc__nm_put_ievent(sock->mgr, event); diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 0bad9ceaf5d..936fa963d9c 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -122,6 +122,7 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) { REQUIRE(sock->type == isc_nm_udpsocket); REQUIRE(sock->iface != NULL); REQUIRE(sock->parent != NULL); + REQUIRE(sock->tid == isc_nm_tid()); uv_udp_init(&worker->loop, &sock->uv_handle.udp); uv_handle_set_data(&sock->uv_handle.handle, NULL); @@ -164,7 +165,8 @@ udp_close_cb(uv_handle_t *handle) { static void stop_udp_child(isc_nmsocket_t *sock) { - INSIST(sock->type == isc_nm_udpsocket); + REQUIRE(sock->type == isc_nm_udpsocket); + REQUIRE(sock->tid == isc_nm_tid()); uv_udp_recv_stop(&sock->uv_handle.udp); uv_close((uv_handle_t *) &sock->uv_handle.udp, udp_close_cb); @@ -179,13 +181,15 @@ stop_udp_child(isc_nmsocket_t *sock) { static void stoplistening(isc_nmsocket_t *sock) { - INSIST(sock->type == isc_nm_udplistener); + REQUIRE(sock->type == isc_nm_udplistener); + /* * Socket is already closing; there's nothing to do. */ if (!isc__nmsocket_active(sock)) { return; } + /* * Mark it inactive now so that all sends will be ignored * and we won't try to stop listening again. @@ -195,7 +199,7 @@ stoplistening(isc_nmsocket_t *sock) { for (int i = 0; i < sock->nchildren; i++) { isc__netievent_udpstop_t *event = NULL; - if (i == sock->tid) { + if (isc_nm_tid() == sock->children[i].tid) { stop_udp_child(&sock->children[i]); continue; }