Commit f95ba8aa authored by Mark Andrews's avatar Mark Andrews
Browse files

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 <null>
    #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 <null> <null>
parent 8c4cf5d2
Pipeline #53920 failed with stages
in 17 minutes and 9 seconds
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment