diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index fdbdea2ff1..d7dea130c9 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -1609,7 +1609,6 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { dns_dispatch_t *disp = resp->disp; dns_dispatchmgr_t *mgr = disp->mgr; dns_qid_t *qid = mgr->qid; - dispatch_cb_t connected = NULL; dispatch_cb_t response = NULL; LOCK(&disp->lock); @@ -1631,9 +1630,6 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { break; case DNS_DISPATCHSTATE_CONNECTING: - dns_dispentry_ref(resp); /* DISPENTRY008 */ - ISC_LIST_UNLINK(disp->pending, resp, plink); - connected = resp->connected; break; case DNS_DISPATCHSTATE_CONNECTED: @@ -1664,12 +1660,6 @@ udp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { unlock: UNLOCK(&disp->lock); - if (connected) { - dispentry_log(resp, LVL(90), "connect callback: %s", - isc_result_totext(result)); - connected(result, NULL, resp->arg); - dns_dispentry_detach(&resp); /* DISPENTRY008 */ - } if (response) { dispentry_log(resp, LVL(90), "read callback: %s", isc_result_totext(result)); @@ -1687,7 +1677,6 @@ tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { dns_dispatch_t *disp = resp->disp; dns_dispatchmgr_t *mgr = disp->mgr; dns_qid_t *qid = mgr->qid; - dispatch_cb_t connected = NULL; dns_displist_t resps = ISC_LIST_INITIALIZER; LOCK(&disp->lock); @@ -1705,8 +1694,6 @@ tcp_dispentry_cancel(dns_dispentry_t *resp, isc_result_t result) { break; case DNS_DISPATCHSTATE_CONNECTING: - ISC_LIST_UNLINK(disp->pending, resp, plink); - connected = resp->connected; break; case DNS_DISPATCHSTATE_CONNECTED: @@ -1774,20 +1761,13 @@ unlock: UNLOCK(&disp->lock); /* - * NOTE: Calling the connected and response callbacks directly from here - * should be done asynchronously, as the dns_dispatch_done() is usually - * called directly from the response callback, so there's a slight - * chance that the call stack will get higher here, but it's mitigated - * by the ".reading" flag, so we don't ever go into a loop. + * NOTE: Calling the response callback directly from here should be done + * asynchronously, as the dns_dispatch_done() is usually called directly + * from the response callback, so there's a slight chance that the call + * stack will get higher here, but it's mitigated by the ".reading" + * flag, so we don't ever go into a loop. */ - if (connected) { - dispentry_log(resp, LVL(90), "connect callback: %s", - isc_result_totext(result)); - connected(result, NULL, resp->arg); - dns_dispentry_detach(&resp); /* DISPENTRY005 */ - } - tcp_recv_processall(&resps, NULL); } @@ -1888,7 +1868,29 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { LOCK(&disp->lock); INSIST(disp->state == DNS_DISPATCHSTATE_CONNECTING); - if (ISC_LIST_EMPTY(disp->pending)) { + /* + * If there are pending responses, call the connect + * callbacks for all of them. + */ + for (resp = ISC_LIST_HEAD(disp->pending); resp != NULL; resp = next) { + next = ISC_LIST_NEXT(resp, plink); + ISC_LIST_UNLINK(disp->pending, resp, plink); + ISC_LIST_APPEND(resps, resp, rlink); + resp->result = eresult; + + if (resp->state == DNS_DISPATCHSTATE_CANCELED) { + resp->result = ISC_R_CANCELED; + } else if (eresult == ISC_R_SUCCESS) { + resp->state = DNS_DISPATCHSTATE_CONNECTED; + ISC_LIST_APPEND(disp->active, resp, alink); + resp->reading = true; + dispentry_log(resp, LVL(90), "start reading"); + } else { + resp->state = DNS_DISPATCHSTATE_NONE; + } + } + + if (ISC_LIST_EMPTY(disp->active)) { /* All responses have been canceled */ disp->state = DNS_DISPATCHSTATE_CANCELED; } else if (eresult == ISC_R_SUCCESS) { @@ -1898,24 +1900,6 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { disp->state = DNS_DISPATCHSTATE_NONE; } - /* - * If there are pending responses, call the connect - * callbacks for all of them. - */ - for (resp = ISC_LIST_HEAD(disp->pending); resp != NULL; resp = next) { - next = ISC_LIST_NEXT(resp, plink); - ISC_LIST_UNLINK(disp->pending, resp, plink); - ISC_LIST_APPEND(resps, resp, rlink); - - if (eresult == ISC_R_SUCCESS) { - resp->state = DNS_DISPATCHSTATE_CONNECTED; - ISC_LIST_APPEND(disp->active, resp, alink); - resp->reading = true; - dispentry_log(resp, LVL(90), "start reading"); - } else { - resp->state = DNS_DISPATCHSTATE_NONE; - } - } UNLOCK(&disp->lock); for (resp = ISC_LIST_HEAD(resps); resp != NULL; resp = next) { @@ -1923,8 +1907,8 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { ISC_LIST_UNLINK(resps, resp, rlink); dispentry_log(resp, LVL(90), "connect callback: %s", - isc_result_totext(eresult)); - resp->connected(eresult, NULL, resp->arg); + isc_result_totext(resp->result)); + resp->connected(resp->result, NULL, resp->arg); dns_dispentry_detach(&resp); /* DISPENTRY005 */ } @@ -1946,8 +1930,9 @@ udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { switch (resp->state) { case DNS_DISPATCHSTATE_CANCELED: - UNLOCK(&disp->lock); - goto detach; + eresult = ISC_R_CANCELED; + ISC_LIST_UNLINK(disp->pending, resp, plink); + goto unlock; case DNS_DISPATCHSTATE_CONNECTING: ISC_LIST_UNLINK(disp->pending, resp, plink); break; @@ -1956,6 +1941,8 @@ udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { } switch (eresult) { + case ISC_R_CANCELED: + break; case ISC_R_SUCCESS: resp->state = DNS_DISPATCHSTATE_CONNECTED; udp_startrecv(handle, resp); @@ -1978,7 +1965,7 @@ udp_connected(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { resp->state = DNS_DISPATCHSTATE_NONE; break; } - +unlock: UNLOCK(&disp->lock); dispentry_log(resp, LVL(90), "connect callback: %s",