diff --git a/bin/named/client.c b/bin/named/client.c index 2deb766e02..d3fbfe6bce 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -126,7 +126,6 @@ maybe_free(ns_client_t *client) { /* We have received our last event. */ ns_query_free(client); isc_mempool_destroy(&client->sendbufs); - dns_message_destroy(&client->message); isc_timer_detach(&client->timer); if (client->dispentry != NULL) { @@ -139,6 +138,14 @@ maybe_free(ns_client_t *client) { &client->dispentry, deventp); } + if (client->view != NULL) + dns_view_detach(&client->view); + if (client->opt != NULL) { + INSIST(dns_rdataset_isassociated(client->opt)); + dns_rdataset_disassociate(client->opt); + dns_message_puttemprdataset(client->message, &client->opt); + } + dns_message_destroy(&client->message); if (client->tcpmsg_valid) dns_tcpmsg_invalidate(&client->tcpmsg); if (client->dispatch != NULL) @@ -488,6 +495,10 @@ client_addopt(ns_client_t *client) { return (ISC_R_SUCCESS); } +/* + * Handle an incoming request event from the dispatch (UDP case) + * or tcpmsg (TCP case). + */ static void client_request(isc_task_t *task, isc_event_t *event) { ns_client_t *client; @@ -898,13 +909,16 @@ ns_client_wait(ns_client_t *client) { } isc_boolean_t +ns_client_shuttingdown(ns_client_t *client) { + return (client->shuttingdown); +} + +void ns_client_unwait(ns_client_t *client) { - isc_boolean_t shuttingdown = client->shuttingdown; client->nwaiting--; INSIST(client->nwaiting >= 0); - if (shuttingdown) + if (client->shuttingdown) maybe_free(client); - return (shuttingdown); } /*** diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 096b47aba9..cf1fe10114 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -98,10 +98,16 @@ ns_client_destroy(ns_client_t *client); isc_result_t ns_client_newnamebuf(ns_client_t *client); +isc_boolean_t +ns_client_shuttingdown(ns_client_t *client); +/* + * Return ISC_TRUE iff the client is currently shutting down. + */ + void ns_client_wait(ns_client_t *client); -isc_boolean_t +void ns_client_unwait(ns_client_t *client); isc_result_t diff --git a/bin/named/query.c b/bin/named/query.c index 8f1f364a15..1b51e8f34f 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -1627,8 +1627,7 @@ static void query_resume(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *devent = (dns_fetchevent_t *)event; ns_client_t *client; - isc_boolean_t want_find, client_shuttingdown; - isc_stdtime_t now; + isc_boolean_t fetch_cancelled, client_shuttingdown; /* * Resume a query after recursion. @@ -1640,49 +1639,48 @@ query_resume(isc_task_t *task, isc_event_t *event) { REQUIRE(task == client->task); REQUIRE(RECURSING(client)); - if (devent->fetch == client->query.fetch) { + if (devent->fetch != NULL) { /* * This is the fetch we've been waiting for. */ + INSIST(devent->fetch == client->query.fetch); client->query.fetch = NULL; - want_find = ISC_TRUE; + fetch_cancelled = ISC_FALSE; /* - * Update client->now, if we can. + * Update client->now. */ - isc_stdtime_get(&now); + isc_stdtime_get(&client->now); } else { /* * This is a fetch completion event for a cancelled fetch. * Clean up and don't resume the find. */ + fetch_cancelled = ISC_TRUE; + } + INSIST(client->query.fetch == NULL); + + client->query.attributes &= ~NS_QUERYATTR_RECURSING; + dns_resolver_destroyfetch(client->view->resolver, &devent->fetch); + + /* + * If this client is shutting down, or this transaction + * has timed out, do not resume the find. + */ + client_shuttingdown = ns_client_shuttingdown(client); + if (fetch_cancelled || client_shuttingdown) { if (devent->node != NULL) dns_db_detachnode(devent->db, &devent->node); if (devent->db != NULL) dns_db_detach(&devent->db); query_putrdataset(client, &devent->rdataset); query_putrdataset(client, &devent->sigrdataset); - want_find = ISC_FALSE; - } - - client->query.attributes &= ~NS_QUERYATTR_RECURSING; - dns_resolver_destroyfetch(client->view->resolver, &devent->fetch); - - /* - * XXXRTH If this client is shutting down, or this transaction - * has timed out, do not resume the find. - * - * We should probably have a "unwait" function that - * decrements waiting and tells us whether we should continue, - * do nothing, or reset the client (resetting would cause the - * client to continue with shutdown if it was in shutdown - * mode). - */ - client_shuttingdown = ns_client_unwait(client); - if (client_shuttingdown) - return; - - if (want_find) + isc_event_free(&event); + /* This may destroy the client. */ + ns_client_unwait(client); + } else { + ns_client_unwait(client); query_find(client, devent); + } } static isc_result_t