mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-24 23:57:30 -04:00
Ignore TCP dispatches that have zero references
The TCP dispatches are removed from the dispatchmgr->list in the dispatch_destroy() and there's a brief period of time where dns_dispatch_gettcp() can find a dispatch in connected state that's being destroyed. Set the dispatch state to DNS_DISPATCHSTATE_NONE in the TCP connection callback if there are no responses waiting, and ignore TCP dispatches with zero references in dns_dispatch_gettcp().
This commit is contained in:
parent
90cd14f620
commit
3fac4ca57e
1 changed files with 38 additions and 26 deletions
|
|
@ -764,6 +764,7 @@ tcp_recv_shutdown(dns_dispatch_t *disp, dns_displist_t *resps,
|
|||
next = ISC_LIST_NEXT(resp, alink);
|
||||
tcp_recv_add(resps, resp, result);
|
||||
}
|
||||
disp->state = DNS_DISPATCHSTATE_CANCELED;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1258,34 +1259,42 @@ dns_dispatch_gettcp(dns_dispatchmgr_t *mgr, const isc_sockaddr_t *destaddr,
|
|||
* 2. destination address is same
|
||||
* 3. local address is either NULL or same
|
||||
*/
|
||||
if (disp->socktype == isc_socktype_tcp &&
|
||||
isc_sockaddr_equal(destaddr, &peeraddr) &&
|
||||
(localaddr == NULL ||
|
||||
isc_sockaddr_eqaddr(localaddr, &sockname)))
|
||||
if (disp->socktype != isc_socktype_tcp ||
|
||||
!isc_sockaddr_equal(destaddr, &peeraddr) ||
|
||||
(localaddr != NULL &&
|
||||
!isc_sockaddr_eqaddr(localaddr, &sockname)))
|
||||
{
|
||||
switch (disp->state) {
|
||||
case DNS_DISPATCHSTATE_NONE:
|
||||
/* Dispatch in indeterminate state, skip it */
|
||||
UNLOCK(&disp->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (disp->state) {
|
||||
case DNS_DISPATCHSTATE_NONE:
|
||||
/* A dispatch in indeterminate state, skip it */
|
||||
break;
|
||||
case DNS_DISPATCHSTATE_CONNECTED:
|
||||
if (ISC_LIST_EMPTY(disp->active)) {
|
||||
/* Ignore dispatch with no responses */
|
||||
break;
|
||||
case DNS_DISPATCHSTATE_CONNECTED:
|
||||
/* We found a connected dispatch */
|
||||
dns_dispatch_attach(disp, &disp_connected);
|
||||
break;
|
||||
case DNS_DISPATCHSTATE_CONNECTING:
|
||||
/* We found "a" dispatch, store it for later */
|
||||
if (disp_fallback == NULL) {
|
||||
dns_dispatch_attach(disp,
|
||||
&disp_fallback);
|
||||
}
|
||||
break;
|
||||
case DNS_DISPATCHSTATE_CANCELED:
|
||||
/*
|
||||
* We found a canceled dispatch, skip it.
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
/* We found a connected dispatch */
|
||||
dns_dispatch_attach(disp, &disp_connected);
|
||||
break;
|
||||
case DNS_DISPATCHSTATE_CONNECTING:
|
||||
if (ISC_LIST_EMPTY(disp->pending)) {
|
||||
/* Ignore dispatch with no responses */
|
||||
break;
|
||||
}
|
||||
/* We found "a" dispatch, store it for later */
|
||||
if (disp_fallback == NULL) {
|
||||
dns_dispatch_attach(disp, &disp_fallback);
|
||||
}
|
||||
break;
|
||||
case DNS_DISPATCHSTATE_CANCELED:
|
||||
/* A canceled dispatch, skip it. */
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
UNLOCK(&disp->lock);
|
||||
|
|
@ -1879,7 +1888,10 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) {
|
|||
LOCK(&disp->lock);
|
||||
INSIST(disp->state == DNS_DISPATCHSTATE_CONNECTING);
|
||||
|
||||
if (eresult == ISC_R_SUCCESS) {
|
||||
if (ISC_LIST_EMPTY(disp->pending)) {
|
||||
/* All responses have been canceled */
|
||||
disp->state = DNS_DISPATCHSTATE_CANCELED;
|
||||
} else if (eresult == ISC_R_SUCCESS) {
|
||||
disp->state = DNS_DISPATCHSTATE_CONNECTED;
|
||||
tcp_startrecv(handle, disp, resp);
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue