mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
the client and query data structures were not cleaned up
correctly if the server got a SIGINT with a recursive query in progress
This commit is contained in:
@@ -126,7 +126,6 @@ maybe_free(ns_client_t *client) {
|
|||||||
/* We have received our last event. */
|
/* We have received our last event. */
|
||||||
ns_query_free(client);
|
ns_query_free(client);
|
||||||
isc_mempool_destroy(&client->sendbufs);
|
isc_mempool_destroy(&client->sendbufs);
|
||||||
dns_message_destroy(&client->message);
|
|
||||||
isc_timer_detach(&client->timer);
|
isc_timer_detach(&client->timer);
|
||||||
|
|
||||||
if (client->dispentry != NULL) {
|
if (client->dispentry != NULL) {
|
||||||
@@ -139,6 +138,14 @@ maybe_free(ns_client_t *client) {
|
|||||||
&client->dispentry,
|
&client->dispentry,
|
||||||
deventp);
|
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)
|
if (client->tcpmsg_valid)
|
||||||
dns_tcpmsg_invalidate(&client->tcpmsg);
|
dns_tcpmsg_invalidate(&client->tcpmsg);
|
||||||
if (client->dispatch != NULL)
|
if (client->dispatch != NULL)
|
||||||
@@ -488,6 +495,10 @@ client_addopt(ns_client_t *client) {
|
|||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle an incoming request event from the dispatch (UDP case)
|
||||||
|
* or tcpmsg (TCP case).
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
client_request(isc_task_t *task, isc_event_t *event) {
|
client_request(isc_task_t *task, isc_event_t *event) {
|
||||||
ns_client_t *client;
|
ns_client_t *client;
|
||||||
@@ -898,13 +909,16 @@ ns_client_wait(ns_client_t *client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isc_boolean_t
|
isc_boolean_t
|
||||||
|
ns_client_shuttingdown(ns_client_t *client) {
|
||||||
|
return (client->shuttingdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
ns_client_unwait(ns_client_t *client) {
|
ns_client_unwait(ns_client_t *client) {
|
||||||
isc_boolean_t shuttingdown = client->shuttingdown;
|
|
||||||
client->nwaiting--;
|
client->nwaiting--;
|
||||||
INSIST(client->nwaiting >= 0);
|
INSIST(client->nwaiting >= 0);
|
||||||
if (shuttingdown)
|
if (client->shuttingdown)
|
||||||
maybe_free(client);
|
maybe_free(client);
|
||||||
return (shuttingdown);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@@ -98,10 +98,16 @@ ns_client_destroy(ns_client_t *client);
|
|||||||
isc_result_t
|
isc_result_t
|
||||||
ns_client_newnamebuf(ns_client_t *client);
|
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
|
void
|
||||||
ns_client_wait(ns_client_t *client);
|
ns_client_wait(ns_client_t *client);
|
||||||
|
|
||||||
isc_boolean_t
|
void
|
||||||
ns_client_unwait(ns_client_t *client);
|
ns_client_unwait(ns_client_t *client);
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
|
@@ -1627,8 +1627,7 @@ static void
|
|||||||
query_resume(isc_task_t *task, isc_event_t *event) {
|
query_resume(isc_task_t *task, isc_event_t *event) {
|
||||||
dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
|
dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
|
||||||
ns_client_t *client;
|
ns_client_t *client;
|
||||||
isc_boolean_t want_find, client_shuttingdown;
|
isc_boolean_t fetch_cancelled, client_shuttingdown;
|
||||||
isc_stdtime_t now;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resume a query after recursion.
|
* Resume a query after recursion.
|
||||||
@@ -1640,49 +1639,48 @@ query_resume(isc_task_t *task, isc_event_t *event) {
|
|||||||
REQUIRE(task == client->task);
|
REQUIRE(task == client->task);
|
||||||
REQUIRE(RECURSING(client));
|
REQUIRE(RECURSING(client));
|
||||||
|
|
||||||
if (devent->fetch == client->query.fetch) {
|
if (devent->fetch != NULL) {
|
||||||
/*
|
/*
|
||||||
* This is the fetch we've been waiting for.
|
* This is the fetch we've been waiting for.
|
||||||
*/
|
*/
|
||||||
|
INSIST(devent->fetch == client->query.fetch);
|
||||||
client->query.fetch = NULL;
|
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 {
|
} else {
|
||||||
/*
|
/*
|
||||||
* This is a fetch completion event for a cancelled fetch.
|
* This is a fetch completion event for a cancelled fetch.
|
||||||
* Clean up and don't resume the find.
|
* 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)
|
if (devent->node != NULL)
|
||||||
dns_db_detachnode(devent->db, &devent->node);
|
dns_db_detachnode(devent->db, &devent->node);
|
||||||
if (devent->db != NULL)
|
if (devent->db != NULL)
|
||||||
dns_db_detach(&devent->db);
|
dns_db_detach(&devent->db);
|
||||||
query_putrdataset(client, &devent->rdataset);
|
query_putrdataset(client, &devent->rdataset);
|
||||||
query_putrdataset(client, &devent->sigrdataset);
|
query_putrdataset(client, &devent->sigrdataset);
|
||||||
want_find = ISC_FALSE;
|
isc_event_free(&event);
|
||||||
}
|
/* This may destroy the client. */
|
||||||
|
ns_client_unwait(client);
|
||||||
client->query.attributes &= ~NS_QUERYATTR_RECURSING;
|
} else {
|
||||||
dns_resolver_destroyfetch(client->view->resolver, &devent->fetch);
|
ns_client_unwait(client);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
query_find(client, devent);
|
query_find(client, devent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
|
Reference in New Issue
Block a user