From d2895dd9bba25beaa167cb1fe9282855bc002768 Mon Sep 17 00:00:00 2001 From: Michael Sawyer Date: Thu, 13 Jul 2000 00:32:20 +0000 Subject: [PATCH] Major changes to how dighost handles lists and shutdown conditions. Probably not safe to pull up to release branch, since, though it works, it needs serious testing and more changes are still pending. In particular, I INSIST lots of things I didn't used to INSIST, which may be set off under certain conditions. --- bin/dig/dighost.c | 497 ++++++++++++++++++++++++---------------------- 1 file changed, 258 insertions(+), 239 deletions(-) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index df7561240e..50b1e6523d 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: dighost.c,v 1.77 2000/07/12 00:42:54 mws Exp $ */ +/* $Id: dighost.c,v 1.78 2000/07/13 00:32:20 mws Exp $ */ /* * Notice to programmers: Do not use this code as an example of how to @@ -88,6 +88,7 @@ isc_sockaddr_t bind_any; char *rootspace[BUFSIZE]; isc_buffer_t rootbuf; int sendcount = 0; +int recvcount = 0; int sockcount = 0; int ndots = -1; int tries = 3; @@ -107,7 +108,7 @@ extern isc_boolean_t isc_mem_debugging; isc_boolean_t debugging = ISC_FALSE; char *progname = NULL; -static isc_boolean_t +static void cancel_lookup(dig_lookup_t *lookup); static int @@ -237,8 +238,7 @@ requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { debug("requeue_lookup()"); - if (free_now) - return(ISC_R_SUCCESS); + INSIST(!free_now); lookup_counter++; if (lookup_counter > LOOKUP_LIMIT) @@ -615,19 +615,114 @@ add_question(dns_message_t *message, dns_name_t *name, } /* - * Return ISC_TRUE if we're in the process of shutting down on the - * return. + * We're done iff all the counts are zero and the lookup list is empty */ +static void +check_if_done(void) { + debug("check_if_done()"); + if ((sockcount == 0) && (recvcount == 0) && (sendcount == 0) + && ISC_LIST_EMPTY(lookup_list)) { + debug("shutting down"); + dighost_shutdown(); + } +} + +/* + * Clear out a query when we're done with it. WARNING: This routine + * WILL invalidate the query pointer. + */ +static void +clear_query(dig_query_t *query) { + dig_lookup_t *lookup; + + REQUIRE(query != NULL); + + lookup = query->lookup; + ISC_LIST_UNLINK(lookup->q, query, link); + if (ISC_LINK_LINKED(&query->recvbuf, link)) + ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf, + link); + if (ISC_LINK_LINKED(&query->lengthbuf, link)) + ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf, + link); + isc_buffer_invalidate(&query->recvbuf); + isc_buffer_invalidate(&query->lengthbuf); + isc_mem_free(mctx, query); +} + static isc_boolean_t -check_next_lookup(dig_lookup_t *lookup) { +try_clear_lookup(dig_lookup_t *lookup) { + dig_server_t *s; + void *ptr; + + REQUIRE(lookup != NULL); + + if (ISC_LIST_HEAD(lookup->q) != NULL) + return (ISC_FALSE); + /* + * At this point, we know there are no queries on the lookup, + * so can make it go away also. + */ + if (lookup->use_my_server_list) { + s = ISC_LIST_HEAD(lookup->my_server_list); + while (s != NULL) { + debug("freeing server %p belonging to %p", + s, lookup); + ptr = s; + s = ISC_LIST_NEXT(s, link); + ISC_LIST_DEQUEUE(lookup->my_server_list, + (dig_server_t *)ptr, link); + isc_mem_free(mctx, ptr); + } + } + if (lookup->sendmsg != NULL) + dns_message_destroy(&lookup->sendmsg); + if (lookup->querysig != NULL) { + debug("freeing buffer %p", lookup->querysig); + isc_buffer_free(&lookup->querysig); + } + if (lookup->timer != NULL) + isc_timer_detach(&lookup->timer); + + ptr = lookup; + lookup = ISC_LIST_NEXT(lookup, link); + ISC_LIST_DEQUEUE(lookup_list, (dig_lookup_t *)ptr, link); + isc_mem_free(mctx, ptr); + return (ISC_TRUE); +} + + +/* + * If we can, start the next lookup in the queue running. + * This assumes that the lookup on the head of the queue hasn't been + * started yet. + */ +static void +begin_next_lookup(void) { dig_lookup_t *next; + + next = ISC_LIST_HEAD(lookup_list); + if (next != NULL) { + setup_lookup(next); + do_lookup(next); + } else { + check_if_done(); + } +} + +/* + * WARNING: The following routine may invalidate the lookup pointer. + * Never depend on being able to reference lookup or query pointers on the + * current lookup after calling this. + */ +static void +check_next_lookup(dig_lookup_t *lookup) { dig_query_t *query; isc_boolean_t still_working=ISC_FALSE; - if (free_now) - return (ISC_TRUE); + INSIST(!free_now); - debug("check_next_lookup(%p)", lookup); + debug("is_lookup_done(%p)", lookup); for (query = ISC_LIST_HEAD(lookup->q); query != NULL; query = ISC_LIST_NEXT(query, link)) { @@ -637,54 +732,11 @@ check_next_lookup(dig_lookup_t *lookup) { } } if (still_working) - return (ISC_FALSE); - - debug("have %d retries left for %s", - lookup->retries-1, lookup->textname); - debug("lookup %s pending", lookup->pending ? "is" : "is not"); - - next = ISC_LIST_NEXT(lookup, link); - - if (lookup->tcp_mode) { - if (next == NULL) { - debug("shutting down", stderr); - dighost_shutdown(); - return (ISC_TRUE); - } - if (next->sendmsg == NULL) { - debug("setting up for TCP"); - setup_lookup(next); - do_lookup(next); - } - } else { - if (!lookup->pending) { - if (next == NULL) { - debug("shutting down", stderr); - dighost_shutdown(); - return (ISC_TRUE); - } - if (next->sendmsg == NULL) { - debug("setting up for UDP"); - setup_lookup(next); - do_lookup(next); - } - } else { - if (lookup->retries > 1) { - debug("retrying"); - lookup->retries --; - if (lookup->timer != NULL) - isc_timer_detach(&lookup->timer); - send_udp(lookup); - } else { - debug("cancelling"); - return(cancel_lookup(lookup)); - } - } - } - return (ISC_FALSE); + return; + if (try_clear_lookup(lookup)) + begin_next_lookup(); } - static void followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section) { @@ -699,9 +751,9 @@ followup_lookup(dns_message_t *msg, dig_query_t *query, isc_boolean_t success = ISC_FALSE; int len; + INSIST(!free_now); + debug("followup_lookup()"); - if (free_now) - return; result = dns_message_firstname(msg,section); if (result != ISC_R_SUCCESS) { debug("firstname returned %s", @@ -810,9 +862,9 @@ next_origin(dns_message_t *msg, dig_query_t *query) { UNUSED(msg); + INSIST(!free_now); + debug("next_origin()"); - if (free_now) - return; debug("following up %s", query->lookup->textname); if (query->lookup->origin == NULL) { @@ -903,12 +955,10 @@ setup_lookup(dig_lookup_t *lookup) { char store[MXNAME]; REQUIRE(lookup != NULL); - + INSIST(!free_now); + debug("setup_lookup(%p)",lookup); - if (free_now) - return; - debug("setting up for looking up %s @%p->%p", lookup->textname, lookup, lookup->link.next); @@ -1142,12 +1192,12 @@ send_done(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); debug("send_done()"); + sendcount--; + debug("sendcount=%d",sendcount); + INSIST(sendcount >= 0); } -/* - * Return ISC_TRUE if we're in the process of shutting down - */ -static isc_boolean_t +void cancel_lookup(dig_lookup_t *lookup) { dig_query_t *query = NULL; @@ -1163,12 +1213,13 @@ cancel_lookup(dig_lookup_t *lookup) { ISC_SOCKCANCEL_ALL); isc_socket_detach(&query->sock); sockcount--; - debug("socket = %d", sockcount); + debug("sockcount=%d", sockcount); + INSIST(sockcount >= 0); + check_if_done(); } } lookup->pending = ISC_FALSE; lookup->retries = 0; - return(check_next_lookup(lookup)); } static void @@ -1214,8 +1265,8 @@ for (query = ISC_LIST_HEAD(lookup->q); result = isc_socket_recvv(query->sock, &query->recvlist, 1, global_task, recv_done, query); check_result(result, "isc_socket_recvv"); - sendcount++; - debug("sent count number %d", sendcount); + recvcount++; + debug("recvcount=%d", recvcount); ISC_LIST_ENQUEUE(query->sendlist, &lookup->sendbuf, link); debug("sending a request"); result = isc_time_now(&query->time_sent); @@ -1225,6 +1276,7 @@ for (query = ISC_LIST_HEAD(lookup->q); global_task, send_done, query, &query->sockaddr, NULL); check_result(result, "isc_socket_sendtov"); + sendcount++; } } @@ -1253,27 +1305,26 @@ connect_timeout(isc_task_t *task, isc_event_t *event) { q != NULL; q = ISC_LIST_NEXT(q, link)) { if (q->working) { - if (!free_now) { - isc_buffer_clear(b); - result = isc_sockaddr_totext(&q->sockaddr, b); - check_result(result, "isc_sockaddr_totext"); - isc_buffer_usedregion(b, &r); - if ((q->lookup->retries > 1) && - (!q->lookup->tcp_mode)) - printf(";; Connection to server %.*s " - "for %s timed out. " - "Retrying %d.\n", - (int)r.length, r.base, - q->lookup->textname, - q->lookup->retries-1); - else { - printf(";; Connection to " - "server %.*s " - "for %s timed out. " - "Giving up.\n", - (int)r.length, r.base, - q->lookup->textname); - } + INSIST(!free_now); + isc_buffer_clear(b); + result = isc_sockaddr_totext(&q->sockaddr, b); + check_result(result, "isc_sockaddr_totext"); + isc_buffer_usedregion(b, &r); + if ((q->lookup->retries > 1) && + (!q->lookup->tcp_mode)) + printf(";; Connection to server %.*s " + "for %s timed out. " + "Retrying %d.\n", + (int)r.length, r.base, + q->lookup->textname, + q->lookup->retries-1); + else { + printf(";; Connection to " + "server %.*s " + "for %s timed out. " + "Giving up.\n", + (int)r.length, r.base, + q->lookup->textname); } isc_socket_cancel(q->sock, task, ISC_SOCKCANCEL_ALL); @@ -1295,16 +1346,12 @@ tcp_length_done(isc_task_t *task, isc_event_t *event) { isc_uint16_t length; REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); + INSIST(!free_now); UNUSED(task); debug("tcp_length_done()"); - if (free_now) { - isc_event_free(&event); - return; - } - sevent = (isc_socketevent_t *)event; query = event->ev_arg; @@ -1326,9 +1373,10 @@ tcp_length_done(isc_task_t *task, isc_event_t *event) { isc_result_totext(sevent->result)); isc_buffer_free(&b); query->working = ISC_FALSE; - sockcount--; - debug("socket = %d",sockcount); isc_socket_detach(&query->sock); + sockcount--; + debug("sockcount=%d",sockcount); + INSIST(sockcount >= 0); isc_event_free(&event); check_next_lookup(query->lookup); return; @@ -1354,7 +1402,9 @@ tcp_length_done(isc_task_t *task, isc_event_t *event) { result = isc_socket_recvv(query->sock, &query->recvlist, length, task, recv_done, query); check_result(result, "isc_socket_recvv"); - debug("resubmitted recv request with length %d", length); + recvcount++; + debug("resubmitted recv request with length %d, recvcount=%d", + length, recvcount); isc_event_free(&event); } @@ -1362,16 +1412,16 @@ static void launch_next_query(dig_query_t *query, isc_boolean_t include_question) { isc_result_t result; - debug("launch_next_query()"); + INSIST(!free_now); - if (free_now) - return; + debug("launch_next_query()"); if (!query->lookup->pending) { debug("ignoring launch_next_query because !pending"); - sockcount--; - debug("socket = %d", sockcount); isc_socket_detach(&query->sock); + sockcount--; + debug("sockcount=%d", sockcount); + INSIST(sockcount >= 0); query->working = ISC_FALSE; query->waiting_connect = ISC_FALSE; check_next_lookup(query->lookup); @@ -1391,14 +1441,17 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) { result = isc_socket_recvv(query->sock, &query->lengthlist, 0, global_task, tcp_length_done, query); check_result(result, "isc_socket_recvv"); - sendcount++; + recvcount++; + debug("recvcount=%d",recvcount); if (!query->first_soa_rcvd) { debug("sending a request"); result = isc_time_now(&query->time_sent); check_result(result, "isc_time_now"); result = isc_socket_sendv(query->sock, &query->sendlist, global_task, send_done, query); - check_result(result, "isc_socket_recvv"); + check_result(result, "isc_socket_sendv"); + sendcount++; + debug("sendcount=%d", sendcount); } query->waiting_connect = ISC_FALSE; check_next_lookup(query->lookup); @@ -1416,14 +1469,10 @@ connect_done(isc_task_t *task, isc_event_t *event) { UNUSED(task); REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT); + INSIST(!free_now); debug("connect_done()"); - if (free_now) { - isc_event_free(&event); - return; - } - sevent = (isc_socketevent_t *)event; query = sevent->ev_arg; @@ -1644,38 +1693,30 @@ recv_done(isc_task_t *task, isc_event_t *event) { isc_buffer_t ab; char abspace[MXNAME]; isc_region_t r; - dig_lookup_t *n; + dig_lookup_t *n, *l; isc_boolean_t docancel = ISC_FALSE; - isc_boolean_t result_bool; unsigned int local_timeout; UNUSED(task); + INSIST(!free_now); debug("recv_done()"); - if (free_now) { - isc_event_free(&event); - return; - } + recvcount--; + debug("recvcount=%d", recvcount); + INSIST(recvcount >= 0); query = event->ev_arg; debug("lookup=%p, query=%p", query->lookup, query); - if (free_now) { - debug("bailing out, since freeing now"); - isc_event_free(&event); - return; - } + l = query->lookup; - sendcount--; - debug("in recv_done, counter down to %d", sendcount); REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE); sevent = (isc_socketevent_t *)event; - if ((query->lookup->tcp_mode) && - (query->lookup->timer != NULL)) - isc_timer_touch(query->lookup->timer); - if (!query->lookup->pending && !query->lookup->ns_search_only) { + if ((l->tcp_mode) && (l->timer != NULL)) + isc_timer_touch(l->timer); + if (!l->pending && !l->ns_search_only) { debug("no longer pending. Got %s", isc_result_totext(sevent->result)); @@ -1683,10 +1724,8 @@ recv_done(isc_task_t *task, isc_event_t *event) { query->waiting_connect = ISC_FALSE; isc_event_free(&event); - /* - * In this case, we don't actually use result_bool - */ - result_bool = cancel_lookup(query->lookup); + clear_query(query); + check_next_lookup(l); return; } @@ -1698,24 +1737,24 @@ recv_done(isc_task_t *task, isc_event_t *event) { check_result(result, "dns_message_create"); if (key != NULL) { - debug("querysig 1 is %p", query->lookup->querysig); - if (query->lookup->querysig == NULL) { + debug("querysig 1 is %p", l->querysig); + if (l->querysig == NULL) { debug("getting initial querysig"); result = dns_message_getquerytsig( - query->lookup->sendmsg, - mctx, &query->lookup->querysig); + l->sendmsg, + mctx, &l->querysig); check_result(result, "dns_message_getquerytsig"); } result = dns_message_setquerytsig(msg, - query->lookup->querysig); + l->querysig); check_result(result, "dns_message_setquerytsig"); result = dns_message_settsigkey(msg, key); check_result(result, "dns_message_settsigkey"); - msg->tsigctx = query->lookup->tsigctx; - if (query->lookup->msgcounter != 0) + msg->tsigctx = l->tsigctx; + if (l->msgcounter != 0) msg->tcp_continuation = 1; - query->lookup->msgcounter++; + l->msgcounter++; } debug("before parse starts"); result = dns_message_parse(msg, b, ISC_TRUE); @@ -1724,18 +1763,20 @@ recv_done(isc_task_t *task, isc_event_t *event) { hex_dump(b); query->working = ISC_FALSE; query->waiting_connect = ISC_FALSE; - if (!query->lookup->tcp_mode) { + if (!l->tcp_mode) { printf(";; Retrying in TCP mode.\n"); - n = requeue_lookup(query->lookup, ISC_TRUE); + n = requeue_lookup(l, ISC_TRUE); n->tcp_mode = ISC_TRUE; } dns_message_destroy(&msg); isc_event_free(&event); - result_bool = cancel_lookup(query->lookup); + clear_query(query); + cancel_lookup(l); + check_next_lookup(l); return; } if (key != NULL) { - debug("querysig 2 is %p", query->lookup->querysig); + debug("querysig 2 is %p", l->querysig); debug("before verify"); result = dns_tsig_verify(&query->recvbuf, msg, NULL, keyring); @@ -1745,29 +1786,29 @@ recv_done(isc_task_t *task, isc_event_t *event) { dns_result_totext(result)); validated = ISC_FALSE; } - query->lookup->tsigctx = msg->tsigctx; - if (query->lookup->querysig != NULL) { + l->tsigctx = msg->tsigctx; + if (l->querysig != NULL) { debug("freeing querysig buffer %p", - query->lookup->querysig); - isc_buffer_free(&query->lookup->querysig); + l->querysig); + isc_buffer_free(&l->querysig); } result = dns_message_getquerytsig(msg, mctx, - &query->lookup->querysig); + &l->querysig); check_result(result,"dns_message_getquerytsig"); - debug("querysig 3 is %p", query->lookup->querysig); + debug("querysig 3 is %p", l->querysig); } debug("after parse"); - if (query->lookup->xfr_q == NULL) { - query->lookup->xfr_q = query; + if (l->xfr_q == NULL) { + l->xfr_q = query; /* * Once we are in the XFR message, increase * the timeout to much longer, so brief network * outages won't cause the XFR to abort */ if ((timeout != INT_MAX) && - (query->lookup->timer != NULL)) { + (l->timer != NULL)) { if (timeout == 0) { - if (query->lookup->tcp_mode) + if (l->tcp_mode) local_timeout = TCP_TIMEOUT; else local_timeout = UDP_TIMEOUT; @@ -1779,62 +1820,62 @@ recv_done(isc_task_t *task, isc_event_t *event) { } debug("have local timeout of %d", local_timeout); - isc_interval_set(&query->lookup->interval, + isc_interval_set(&l->interval, local_timeout, 0); - result = isc_timer_reset(query->lookup->timer, + result = isc_timer_reset(l->timer, isc_timertype_once, NULL, - &query->lookup->interval, + &l->interval, ISC_FALSE); check_result(result, "isc_timer_reset"); } } - if (query->lookup->xfr_q == query) { - if ((query->lookup->trace)|| - (query->lookup->ns_search_only)) { + if (l->xfr_q == query) { + if ((l->trace)|| + (l->ns_search_only)) { debug("in TRACE code"); if (show_details || (((dns_message_firstname(msg, DNS_SECTION_ANSWER) == ISC_R_SUCCESS)) && - !query->lookup->trace_root)) { + !l->trace_root)) { printmessage(query, msg, ISC_TRUE); } if ((msg->rcode != 0) && - (query->lookup->origin != NULL)) { + (l->origin != NULL)) { next_origin(msg, query); } else { result = dns_message_firstname (msg,DNS_SECTION_ANSWER); if ((result != ISC_R_SUCCESS) || - query->lookup->trace_root) + l->trace_root) followup_lookup(msg, query, DNS_SECTION_AUTHORITY); } } else if ((msg->rcode != 0) && - (query->lookup->origin != NULL)) { + (l->origin != NULL)) { next_origin(msg, query); if (show_details) { printmessage(query, msg, ISC_TRUE); } } else { if (query->first_soa_rcvd && - query->lookup->doing_xfr) + l->doing_xfr) printmessage(query, msg, ISC_FALSE); else printmessage(query, msg, ISC_TRUE); } } else if ((dns_message_firstname(msg, DNS_SECTION_ANSWER) == ISC_R_SUCCESS) && - query->lookup->ns_search_only && - !query->lookup->trace_root ) { + l->ns_search_only && + !l->trace_root ) { printmessage(query, msg, ISC_TRUE); } - if (query->lookup->pending) + if (l->pending) debug("still pending."); - if (query->lookup->doing_xfr) { - if (query != query->lookup->xfr_q) { + if (l->doing_xfr) { + if (query != l->xfr_q) { dns_message_destroy(&msg); isc_event_free (&event); query->working = ISC_FALSE; @@ -1844,7 +1885,8 @@ recv_done(isc_task_t *task, isc_event_t *event) { docancel = check_for_more_data(query, msg, sevent); if (docancel) { dns_message_destroy(&msg); - result_bool = cancel_lookup(query->lookup); + clear_query(query); + cancel_lookup(l); } if (msg != NULL) dns_message_destroy(&msg); @@ -1852,7 +1894,7 @@ recv_done(isc_task_t *task, isc_event_t *event) { } else { if ((msg->rcode == 0) || - (query->lookup->origin == NULL)) { + (l->origin == NULL)) { isc_buffer_init(&ab, abspace, MXNAME); result = isc_sockaddr_totext(&sevent->address, &ab); @@ -1869,17 +1911,16 @@ recv_done(isc_task_t *task, isc_event_t *event) { } query->working = ISC_FALSE; query->lookup->pending = ISC_FALSE; - result_bool = ISC_FALSE; if (!query->lookup->ns_search_only || query->lookup->trace_root) { dns_message_destroy(&msg); - result_bool = cancel_lookup(query->lookup); + cancel_lookup(l); } if (msg != NULL) dns_message_destroy(&msg); isc_event_free(&event); - if ((!free_now) && (!result_bool)) - check_next_lookup(query->lookup); + clear_query(query); + check_next_lookup(l); } return; } @@ -1892,7 +1933,8 @@ recv_done(isc_task_t *task, isc_event_t *event) { query->working = ISC_FALSE; query->waiting_connect = ISC_FALSE; isc_event_free(&event); - check_next_lookup(query->lookup); + clear_query(query); + check_next_lookup(l); return; } fatal("recv_done got result %s", @@ -1972,13 +2014,13 @@ do_lookup_tcp(dig_lookup_t *lookup) { query->waiting_connect = ISC_TRUE; get_address(query->servname, port, &query->sockaddr); - sockcount++; - debug("socket = %d",sockcount); ENSURE(query->sock == NULL); result = isc_socket_create(socketmgr, isc_sockaddr_pf(&query->sockaddr), isc_sockettype_tcp, &query->sock) ; check_result(result, "isc_socket_create"); + sockcount++; + debug("sockcount=%d",sockcount); if (specified_source) result = isc_socket_bind(query->sock, &bind_address); else { @@ -2011,12 +2053,12 @@ do_lookup_udp(dig_lookup_t *lookup) { query->waiting_connect = ISC_FALSE; get_address(query->servname, port, &query->sockaddr); - sockcount++; - debug("socket = %d", sockcount); result = isc_socket_create(socketmgr, isc_sockaddr_pf(&query->sockaddr), isc_sockettype_udp, &query->sock); check_result(result, "isc_socket_create"); + sockcount++; + debug("sockcount=%d", sockcount); if (specified_source) result = isc_socket_bind(query->sock, &bind_address); else { @@ -2048,10 +2090,9 @@ void start_lookup(void) { dig_lookup_t *lookup; - debug("start_lookup()"); + INSIST(!free_now); - if (free_now) - return; + debug("start_lookup()"); lookup = ISC_LIST_HEAD(lookup_list); if (lookup != NULL) { @@ -2067,20 +2108,16 @@ onrun_callback(isc_task_t *task, isc_event_t *event) { start_lookup(); } -void -free_lists(void) { - void *ptr; +#if 0 +/* + * This will be used in the SIGINT handler, and perhaps other places. + */ +static void +cancel_all(void) { dig_lookup_t *l; dig_query_t *q; - dig_server_t *s; - dig_searchlist_t *o; - debug("free_lists()"); - - if (free_now) - return; - - free_now = ISC_TRUE; + debug ("cancel_all()"); l = ISC_LIST_HEAD(lookup_list); while (l != NULL) { @@ -2095,12 +2132,35 @@ free_lists(void) { ISC_SOCKCANCEL_ALL); isc_socket_detach(&q->sock); sockcount--; - debug("socket = %d",sockcount); + debug("sockcount=%d",sockcount); + INSIST(sockcount >= 0); + check_if_done(); } q = ISC_LIST_NEXT(q, link); } l = ISC_LIST_NEXT(l, link); } + check_if_done(); +} +#endif + +void +free_lists(void) { + void *ptr; + dig_server_t *s; + dig_searchlist_t *o; + + debug("free_lists()"); + + REQUIRE(sockcount == 0); + REQUIRE(recvcount == 0); + REQUIRE(sendcount == 0); + + INSIST(ISC_LIST_HEAD(lookup_list) == NULL); + INSIST(!free_now); + + free_now = ISC_TRUE; + s = ISC_LIST_HEAD(server_list); while (s != NULL) { debug("freeing global server %p", s); @@ -2136,47 +2196,6 @@ free_lists(void) { if (namebuf != NULL) isc_buffer_free(&namebuf); - l = ISC_LIST_HEAD(lookup_list); - while (l != NULL) { - q = ISC_LIST_HEAD(l->q); - while (q != NULL) { - debug("freeing query %p, belonging to %p", - q, l); - if (ISC_LINK_LINKED(&q->recvbuf, link)) - ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf, - link); - if (ISC_LINK_LINKED(&q->lengthbuf, link)) - ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf, - link); - isc_buffer_invalidate(&q->recvbuf); - isc_buffer_invalidate(&q->lengthbuf); - ptr = q; - q = ISC_LIST_NEXT(q, link); - isc_mem_free(mctx, ptr); - } - if (l->use_my_server_list) { - s = ISC_LIST_HEAD(l->my_server_list); - while (s != NULL) { - debug("freeing server %p belonging to %p", - s, l); - ptr = s; - s = ISC_LIST_NEXT(s, link); - isc_mem_free(mctx, ptr); - - } - } - if (l->sendmsg != NULL) - dns_message_destroy(&l->sendmsg); - if (l->querysig != NULL) { - debug("freeing buffer %p", l->querysig); - isc_buffer_free(&l->querysig); - } - - ptr = l; - l = ISC_LIST_NEXT(l, link); - isc_mem_free(mctx, ptr); - } - if (keyring != NULL) { debug("freeing keyring %p", keyring); dns_tsigkeyring_destroy(&keyring);