From: Mark Andrews Date: Mon, 12 Oct 2020 06:51:09 +0000 (+1100) Subject: Complete the isc_nmhandle_detach() in the worker thread. X-Git-Tag: v9.17.7~57^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f95ba8aa2071fa72e3730eeb8ee78ef9454ffa5b;p=thirdparty%2Fbind9.git Complete the isc_nmhandle_detach() in the worker thread. isc_nmhandle_detach() needs to complete in the same thread as shutdown_walk_cb() to avoid a race. Clear the caller's pointer then pass control to the worker if necessary. WARNING: ThreadSanitizer: data race Write of size 8 at 0x000000000001 by thread T1: #0 isc_nmhandle_detach lib/isc/netmgr/netmgr.c:1258:15 #1 control_command bin/named/controlconf.c:388:3 #2 dispatch lib/isc/task.c:1152:7 #3 run lib/isc/task.c:1344:2 Previous read of size 8 at 0x000000000001 by thread T2: #0 isc_nm_pauseread lib/isc/netmgr/netmgr.c:1449:33 #1 recv_data lib/isccc/ccmsg.c:109:2 #2 isc__nm_tcp_shutdown lib/isc/netmgr/tcp.c:1157:4 #3 shutdown_walk_cb lib/isc/netmgr/netmgr.c:1515:3 #4 uv_walk #5 process_queue lib/isc/netmgr/netmgr.c:659:4 #6 process_normal_queue lib/isc/netmgr/netmgr.c:582:10 #7 process_queues lib/isc/netmgr/netmgr.c:590:8 #8 async_cb lib/isc/netmgr/netmgr.c:548:2 #9 --- diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 4d6ef881930..b9a96727838 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -164,6 +164,7 @@ typedef enum isc__netievent_type { netievent_udplisten, netievent_tcplisten, netievent_resume, + netievent_detach, } isc__netievent_type; typedef union { @@ -247,6 +248,8 @@ typedef struct isc__netievent__socket_handle { isc_nmhandle_t *handle; } isc__netievent__socket_handle_t; +typedef isc__netievent__socket_handle_t isc__netievent_detach_t; + typedef struct isc__netievent__socket_quota { isc__netievent_type type; isc_nmsocket_t *sock; diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index c1eb14005ae..8358ee4e61a 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -145,6 +145,11 @@ static void isc__nm_async_pausecb(isc__networker_t *worker, isc__netievent_t *ev0); static void isc__nm_async_resumecb(isc__networker_t *worker, isc__netievent_t *ev0); +static void +isc__nm_async_detach(isc__networker_t *worker, isc__netievent_t *ev0); + +static void +nmhandle_detach_cb(isc_nmhandle_t **handlep); int isc_nm_tid(void) { @@ -655,6 +660,9 @@ process_queue(isc__networker_t *worker, isc_queue_t *queue) { case netievent_closecb: isc__nm_async_closecb(worker, ievent); break; + case netievent_detach: + isc__nm_async_detach(worker, ievent); + break; case netievent_shutdown: isc__nm_async_shutdown(worker, ievent); break; @@ -1247,6 +1255,30 @@ isc_nmhandle_detach(isc_nmhandle_t **handlep) { handle = *handlep; *handlep = NULL; + sock = handle->sock; + if (sock->tid == isc_nm_tid()) { + nmhandle_detach_cb(&handle); + } else { + isc__netievent_detach_t *event = + isc__nm_get_ievent(sock->mgr, netievent_detach); + event->handle = handle; /* implict attach */ + isc__nmsocket_attach(sock, &event->sock); + isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid], + (isc__netievent_t *)event); + } +} + +static void +nmhandle_detach_cb(isc_nmhandle_t **handlep) { + isc_nmsocket_t *sock = NULL; + isc_nmhandle_t *handle = NULL; + + REQUIRE(handlep != NULL); + REQUIRE(VALID_NMHANDLE(*handlep)); + + handle = *handlep; + *handlep = NULL; + if (isc_refcount_decrement(&handle->references) > 1) { return; } @@ -1506,6 +1538,20 @@ isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ev0) { isc__nmsocket_detach(&ievent->sock); } +void +isc__nm_async_detach(isc__networker_t *worker, isc__netievent_t *ev0) { + isc__netievent_detach_t *ievent = (isc__netievent_detach_t *)ev0; + + REQUIRE(VALID_NMSOCK(ievent->sock)); + REQUIRE(ievent->sock->tid == isc_nm_tid()); + REQUIRE(ievent->handle != NULL); + + UNUSED(worker); + + isc__nmsocket_detach(&ievent->sock); + nmhandle_detach_cb(&ievent->handle); +} + static void shutdown_walk_cb(uv_handle_t *handle, void *arg) { UNUSED(arg);