diff --git a/lib/ns/query.c b/lib/ns/query.c index 10a08ce4e0..bbaf1c91b1 100644 --- a/lib/ns/query.c +++ b/lib/ns/query.c @@ -6349,6 +6349,15 @@ query_hookresume(isc_task_t *task, isc_event_t *event) { ISC_LIST_UNLINK(client->manager->recursing, client, rlink); } UNLOCK(&client->manager->reclock); + + /* + * This event is running under a client task, so it's safe to detach + * the fetch handle. And it should be done before resuming query + * processing below, since that may trigger another recursion or + * asynchronous hook event. + */ + isc_nmhandle_detach(&client->fetchhandle); + client->state = NS_CLIENTSTATE_WORKING; if (canceled) { @@ -6450,7 +6459,6 @@ query_hookresume(isc_task_t *task, isc_event_t *event) { qctx_destroy(qctx); isc_mem_put(client->mctx, qctx, sizeof(*qctx)); isc_event_free(&event); - isc_nmhandle_detach(&client->fetchhandle); } isc_result_t diff --git a/lib/ns/tests/query_test.c b/lib/ns/tests/query_test.c index 0f6a598c5b..d5943bc775 100644 --- a/lib/ns/tests/query_test.c +++ b/lib/ns/tests/query_test.c @@ -717,7 +717,12 @@ hook_recurse_common(void *arg, void *data, isc_result_t *resultp, asdata->async = true; } } else { - /* Resume from the completion of recursion */ + /* + * Resume from the completion of async event. + * fetchhandle should have been detached so that we can start + * another async event or DNS recursive resolution. + */ + INSIST(qctx->client->fetchhandle == NULL); asdata->async = false; switch (hookpoint) { case NS_QUERY_GOT_ANSWER_BEGIN: