mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-23 10:39:16 +00:00
netmgr: have a single source of truth for tcpdns callback
We pass interface as an opaque argument to tcpdns listening socket. If we stop listening on an interface but still have in-flight connections the opaque 'interface' is not properly reference counted, and we might hit a dead memory. We put just a single source of truth in a listening socket and make the child sockets use that instead of copying the value from listening socket. We clean the callback when we stop listening.
This commit is contained in:
parent
0d637b5985
commit
eda4300bbb
@ -347,7 +347,10 @@ struct isc_nmsocket {
|
|||||||
int tid;
|
int tid;
|
||||||
isc_nmsocket_type type;
|
isc_nmsocket_type type;
|
||||||
isc_nm_t *mgr;
|
isc_nm_t *mgr;
|
||||||
|
/*% Parent socket for multithreaded listeners */
|
||||||
isc_nmsocket_t *parent;
|
isc_nmsocket_t *parent;
|
||||||
|
/*% Listener socket this connection was accepted on */
|
||||||
|
isc_nmsocket_t *listener;
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* quota is the TCP client, attached when a TCP connection
|
* quota is the TCP client, attached when a TCP connection
|
||||||
|
@ -121,10 +121,8 @@ dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
|
|||||||
isc__nmsocket_init(dnssock, handle->sock->mgr,
|
isc__nmsocket_init(dnssock, handle->sock->mgr,
|
||||||
isc_nm_tcpdnssocket, handle->sock->iface);
|
isc_nm_tcpdnssocket, handle->sock->iface);
|
||||||
|
|
||||||
/* We need to copy read callbacks from outer socket */
|
|
||||||
dnssock->rcb.recv = dnslistensock->rcb.recv;
|
|
||||||
dnssock->rcbarg = dnslistensock->rcbarg;
|
|
||||||
dnssock->extrahandlesize = dnslistensock->extrahandlesize;
|
dnssock->extrahandlesize = dnslistensock->extrahandlesize;
|
||||||
|
isc_nmsocket_attach(dnslistensock, &dnssock->listener);
|
||||||
isc_nmsocket_attach(handle->sock, &dnssock->outer);
|
isc_nmsocket_attach(handle->sock, &dnssock->outer);
|
||||||
dnssock->peer = handle->sock->peer;
|
dnssock->peer = handle->sock->peer;
|
||||||
dnssock->read_timeout = handle->sock->mgr->init;
|
dnssock->read_timeout = handle->sock->mgr->init;
|
||||||
@ -171,14 +169,17 @@ processbuffer(isc_nmsocket_t *dnssock, isc_nmhandle_t **handlep) {
|
|||||||
*/
|
*/
|
||||||
len = dnslen(dnssock->buf);
|
len = dnslen(dnssock->buf);
|
||||||
if (len <= dnssock->buf_len - 2) {
|
if (len <= dnssock->buf_len - 2) {
|
||||||
isc_nmhandle_t *dnshandle = NULL;
|
isc_nmhandle_t *dnshandle = isc__nmhandle_get(dnssock,
|
||||||
isc_region_t r2 = {
|
NULL, NULL);
|
||||||
.base = dnssock->buf + 2,
|
isc_nmsocket_t *listener = dnssock->listener;
|
||||||
.length = len
|
|
||||||
};
|
|
||||||
|
|
||||||
dnshandle = isc__nmhandle_get(dnssock, NULL, NULL);
|
if (listener != NULL && listener->rcb.recv != NULL) {
|
||||||
dnssock->rcb.recv(dnshandle, &r2, dnssock->rcbarg);
|
listener->rcb.recv(dnshandle,
|
||||||
|
&(isc_region_t){
|
||||||
|
.base = dnssock->buf + 2,
|
||||||
|
.length = len
|
||||||
|
}, listener->rcbarg);
|
||||||
|
}
|
||||||
|
|
||||||
len += 2;
|
len += 2;
|
||||||
dnssock->buf_len -= len;
|
dnssock->buf_len -= len;
|
||||||
@ -322,6 +323,8 @@ isc_nm_tcpdns_stoplistening(isc_nmsocket_t *sock) {
|
|||||||
|
|
||||||
atomic_store(&sock->listening, false);
|
atomic_store(&sock->listening, false);
|
||||||
atomic_store(&sock->closed, true);
|
atomic_store(&sock->closed, true);
|
||||||
|
sock->rcb.recv = NULL;
|
||||||
|
sock->rcbarg = NULL;
|
||||||
|
|
||||||
if (sock->outer != NULL) {
|
if (sock->outer != NULL) {
|
||||||
isc_nm_tcp_stoplistening(sock->outer);
|
isc_nm_tcp_stoplistening(sock->outer);
|
||||||
@ -502,6 +505,9 @@ tcpdns_close_direct(isc_nmsocket_t *sock) {
|
|||||||
sock->outer->rcb.recv = NULL;
|
sock->outer->rcb.recv = NULL;
|
||||||
isc_nmsocket_detach(&sock->outer);
|
isc_nmsocket_detach(&sock->outer);
|
||||||
}
|
}
|
||||||
|
if (sock->listener != NULL) {
|
||||||
|
isc_nmsocket_detach(&sock->listener);
|
||||||
|
}
|
||||||
/* We don't need atomics here, it's all in single network thread */
|
/* We don't need atomics here, it's all in single network thread */
|
||||||
if (sock->timer_initialized) {
|
if (sock->timer_initialized) {
|
||||||
sock->timer_initialized = false;
|
sock->timer_initialized = false;
|
||||||
|
@ -1625,6 +1625,11 @@ ns__client_request(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
|
|||||||
ifp = (ns_interface_t *) arg;
|
ifp = (ns_interface_t *) arg;
|
||||||
|
|
||||||
mgr = ifp->clientmgr;
|
mgr = ifp->clientmgr;
|
||||||
|
if (mgr == NULL) {
|
||||||
|
/* The interface was shut down in the meantime, just bail */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
REQUIRE(VALID_MANAGER(mgr));
|
REQUIRE(VALID_MANAGER(mgr));
|
||||||
|
|
||||||
client = isc_nmhandle_getdata(handle);
|
client = isc_nmhandle_getdata(handle);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user