mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Synchronise stop listening operation for multi-layer transports
This commit introduces a primitive isc__nmsocket_stop() which performs shutting down on a multilayered socket ensuring the proper order of the operations. The shared data within the socket object can be destroyed after the call completed, as it is guaranteed to not be used from within the context of other worker threads.
This commit is contained in:
@@ -483,6 +483,7 @@ process_netievent(void *arg) {
|
||||
NETIEVENT_CASE(httpendpoints);
|
||||
NETIEVENT_CASE(settlsctx);
|
||||
#endif
|
||||
NETIEVENT_CASE(sockstop);
|
||||
|
||||
NETIEVENT_CASE(connectcb);
|
||||
NETIEVENT_CASE(readcb);
|
||||
@@ -558,6 +559,7 @@ NETIEVENT_SOCKET_DEF(detach);
|
||||
NETIEVENT_SOCKET_QUOTA_DEF(tcpaccept);
|
||||
|
||||
NETIEVENT_SOCKET_TLSCTX_DEF(settlsctx);
|
||||
NETIEVENT_SOCKET_DEF(sockstop);
|
||||
|
||||
void
|
||||
isc__nm_process_ievent(isc__networker_t *worker, isc__netievent_t *event) {
|
||||
@@ -715,6 +717,10 @@ nmsocket_cleanup(isc_nmsocket_t *sock, bool dofree FLARG) {
|
||||
isc__nm_http_cleanup_data(sock);
|
||||
#endif
|
||||
|
||||
if (sock->barrier_initialised) {
|
||||
isc_barrier_destroy(&sock->barrier);
|
||||
}
|
||||
|
||||
sock->magic = 0;
|
||||
|
||||
#ifdef NETMGR_TRACE
|
||||
@@ -2103,6 +2109,66 @@ isc_nm_stoplistening(isc_nmsocket_t *sock) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isc__nmsocket_stop(isc_nmsocket_t *listener) {
|
||||
isc__netievent_sockstop_t ievent = { .sock = listener };
|
||||
|
||||
REQUIRE(VALID_NMSOCK(listener));
|
||||
REQUIRE(listener->tid == isc_tid());
|
||||
REQUIRE(listener->tid == 0);
|
||||
|
||||
if (!atomic_compare_exchange_strong(&listener->closing,
|
||||
&(bool){ false }, true)) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < listener->nchildren; i++) {
|
||||
isc__networker_t *worker =
|
||||
&listener->worker->netmgr->workers[i];
|
||||
isc__netievent_sockstop_t *ev =
|
||||
isc__nm_get_netievent_sockstop(worker, listener);
|
||||
isc__nm_enqueue_ievent(worker, (isc__netievent_t *)ev);
|
||||
}
|
||||
|
||||
isc__nm_async_sockstop(listener->worker, (isc__netievent_t *)&ievent);
|
||||
INSIST(atomic_load(&listener->rchildren) == 0);
|
||||
|
||||
if (!atomic_compare_exchange_strong(&listener->listening,
|
||||
&(bool){ true }, false))
|
||||
{
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
listener->accept_cb = NULL;
|
||||
listener->accept_cbarg = NULL;
|
||||
listener->recv_cb = NULL;
|
||||
listener->recv_cbarg = NULL;
|
||||
|
||||
if (listener->outer != NULL) {
|
||||
isc_nm_stoplistening(listener->outer);
|
||||
isc__nmsocket_detach(&listener->outer);
|
||||
}
|
||||
|
||||
atomic_store(&listener->closed, true);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nmsocket_barrier_init(isc_nmsocket_t *listener) {
|
||||
REQUIRE(listener->nchildren > 0);
|
||||
isc_barrier_init(&listener->barrier, listener->nchildren);
|
||||
listener->barrier_initialised = true;
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_async_sockstop(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
isc__netievent_sockstop_t *ievent = (isc__netievent_sockstop_t *)ev0;
|
||||
isc_nmsocket_t *listener = ievent->sock;
|
||||
UNUSED(worker);
|
||||
|
||||
(void)atomic_fetch_sub(&listener->rchildren, 1);
|
||||
isc_barrier_wait(&listener->barrier);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
|
||||
isc_result_t eresult, bool async) {
|
||||
|
Reference in New Issue
Block a user