mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 23:25:38 +00:00
use separate barriers for "stop" and "listen" operations
On some platforms, when a synchronizing barrier is cleared, one thread can progress while other threads are still in the process of releasing the barrier. If a barrier is reused by the progressing thread during this window, it can cause a deadlock. This can occur if, for example, we stop listening immediately after we start, because the stop and listen functions both use socket->barrier. This has been addressed by using separate barrier objects for stop and listen.
This commit is contained in:
@@ -844,7 +844,8 @@ struct isc_nmsocket {
|
|||||||
isc__networker_t *worker;
|
isc__networker_t *worker;
|
||||||
|
|
||||||
isc_mutex_t lock;
|
isc_mutex_t lock;
|
||||||
isc_barrier_t barrier;
|
isc_barrier_t listen_barrier;
|
||||||
|
isc_barrier_t stop_barrier;
|
||||||
|
|
||||||
/*% Parent socket for multithreaded listeners */
|
/*% Parent socket for multithreaded listeners */
|
||||||
isc_nmsocket_t *parent;
|
isc_nmsocket_t *parent;
|
||||||
@@ -1027,7 +1028,7 @@ struct isc_nmsocket {
|
|||||||
|
|
||||||
atomic_int_fast32_t active_child_connections;
|
atomic_int_fast32_t active_child_connections;
|
||||||
|
|
||||||
bool barrier_initialised;
|
bool barriers_initialised;
|
||||||
bool manual_read_timer;
|
bool manual_read_timer;
|
||||||
#ifdef NETMGR_TRACE
|
#ifdef NETMGR_TRACE
|
||||||
void *backtrace[TRACE_SIZE];
|
void *backtrace[TRACE_SIZE];
|
||||||
|
@@ -676,8 +676,9 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
|
|||||||
#endif
|
#endif
|
||||||
isc__nm_streamdns_cleanup_data(sock);
|
isc__nm_streamdns_cleanup_data(sock);
|
||||||
|
|
||||||
if (sock->barrier_initialised) {
|
if (sock->barriers_initialised) {
|
||||||
isc_barrier_destroy(&sock->barrier);
|
isc_barrier_destroy(&sock->listen_barrier);
|
||||||
|
isc_barrier_destroy(&sock->stop_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
sock->magic = 0;
|
sock->magic = 0;
|
||||||
@@ -2021,8 +2022,9 @@ isc__nmsocket_stop(isc_nmsocket_t *listener) {
|
|||||||
void
|
void
|
||||||
isc__nmsocket_barrier_init(isc_nmsocket_t *listener) {
|
isc__nmsocket_barrier_init(isc_nmsocket_t *listener) {
|
||||||
REQUIRE(listener->nchildren > 0);
|
REQUIRE(listener->nchildren > 0);
|
||||||
isc_barrier_init(&listener->barrier, listener->nchildren);
|
isc_barrier_init(&listener->listen_barrier, listener->nchildren);
|
||||||
listener->barrier_initialised = true;
|
isc_barrier_init(&listener->stop_barrier, listener->nchildren);
|
||||||
|
listener->barriers_initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2032,7 +2034,7 @@ isc__nm_async_sockstop(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
UNUSED(worker);
|
UNUSED(worker);
|
||||||
|
|
||||||
(void)atomic_fetch_sub(&listener->rchildren, 1);
|
(void)atomic_fetch_sub(&listener->rchildren, 1);
|
||||||
isc_barrier_wait(&listener->barrier);
|
isc_barrier_wait(&listener->stop_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -556,7 +556,7 @@ done:
|
|||||||
UNLOCK(&sock->parent->lock);
|
UNLOCK(&sock->parent->lock);
|
||||||
|
|
||||||
REQUIRE(!worker->loop->paused);
|
REQUIRE(!worker->loop->paused);
|
||||||
isc_barrier_wait(&sock->parent->barrier);
|
isc_barrier_wait(&sock->parent->listen_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -691,7 +691,7 @@ isc__nm_async_tcpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
(void)atomic_fetch_sub(&sock->parent->rchildren, 1);
|
(void)atomic_fetch_sub(&sock->parent->rchildren, 1);
|
||||||
|
|
||||||
REQUIRE(!worker->loop->paused);
|
REQUIRE(!worker->loop->paused);
|
||||||
isc_barrier_wait(&sock->parent->barrier);
|
isc_barrier_wait(&sock->parent->stop_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -427,7 +427,7 @@ done:
|
|||||||
UNLOCK(&sock->parent->lock);
|
UNLOCK(&sock->parent->lock);
|
||||||
|
|
||||||
REQUIRE(!worker->loop->paused);
|
REQUIRE(!worker->loop->paused);
|
||||||
isc_barrier_wait(&sock->parent->barrier);
|
isc_barrier_wait(&sock->parent->listen_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -496,7 +496,7 @@ isc__nm_async_udpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
|
|||||||
(void)atomic_fetch_sub(&sock->parent->rchildren, 1);
|
(void)atomic_fetch_sub(&sock->parent->rchildren, 1);
|
||||||
|
|
||||||
REQUIRE(!worker->loop->paused);
|
REQUIRE(!worker->loop->paused);
|
||||||
isc_barrier_wait(&sock->parent->barrier);
|
isc_barrier_wait(&sock->parent->stop_barrier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user