]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2091. [port] dighost.c: race condition on cleanup. [RT #16417]
authorMark Andrews <marka@isc.org>
Mon, 2 Oct 2006 03:08:34 +0000 (03:08 +0000)
committerMark Andrews <marka@isc.org>
Mon, 2 Oct 2006 03:08:34 +0000 (03:08 +0000)
CHANGES
bin/dig/dighost.c
bin/dig/include/dig/dig.h

diff --git a/CHANGES b/CHANGES
index da19eeb1f58e76411eee46085b21e7ff1950f851..f433af6b3d91c0250d076125fc707df48bf004f6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+2091.  [port]          dighost.c: race condition on cleanup. [RT #16417]
+
 2090.  [port]          win32: Visual C++ 2005 command line manifest support.
                        [RT #16417]
 
index 5bcff8ca34572bddad5de6a54a237c7bc119a388..94fd7cb7969b42ecd4b8d52836422b4e58da648b 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dighost.c,v 1.294 2006/08/01 00:49:02 marka Exp $ */
+/* $Id: dighost.c,v 1.295 2006/10/02 03:08:34 marka Exp $ */
 
 /*! \file
  *  \note
@@ -697,6 +697,8 @@ make_empty_lookup(void) {
                fatal("memory allocation failure in %s:%d",
                       __FILE__, __LINE__);
        looknew->pending = ISC_TRUE;
+       looknew->waiting_senddone = ISC_FALSE;
+       looknew->pending_clear = ISC_FALSE;
        looknew->textname[0] = 0;
        looknew->cmdline[0] = 0;
        looknew->rdtype = dns_rdatatype_a;
@@ -1004,9 +1006,8 @@ setup_system(void) {
        if (lwresult != LWRES_R_SUCCESS)
                fatal("lwres_context_create failed");
 
-       if (isc_file_exists(RESOLV_CONF))
-               lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
-       if (lwresult != LWRES_R_SUCCESS)
+       lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
+       if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
                fatal("parse of %s failed", RESOLV_CONF);
 
        lwconf = lwres_conf_get(lwctx);
@@ -1259,7 +1260,10 @@ clear_query(dig_query_t *query) {
        isc_mempool_put(commctx, query->recvspace);
        isc_buffer_invalidate(&query->recvbuf);
        isc_buffer_invalidate(&query->lengthbuf);
-       isc_mem_free(mctx, query);
+       if (lookup->waiting_senddone)
+               query->pending_free = ISC_TRUE;
+       else
+               isc_mem_free(mctx, query);
 }
 
 /*%
@@ -1284,9 +1288,15 @@ try_clear_lookup(dig_lookup_t *lookup) {
                                debug("query to %s still pending", q->servname);
                                q = ISC_LIST_NEXT(q, link);
                        }
-                       return (ISC_FALSE);
                }
+               return (ISC_FALSE);
+       }
+
+       if (lookup->waiting_senddone) {
+               lookup->pending_clear = ISC_TRUE;
+               return (ISC_TRUE);
        }
+
        /*
         * At this point, we know there are no queries on the lookup,
         * so can make it go away also.
@@ -1319,7 +1329,6 @@ try_clear_lookup(dig_lookup_t *lookup) {
        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
@@ -1987,6 +1996,7 @@ setup_lookup(dig_lookup_t *lookup) {
                       query, lookup);
                query->lookup = lookup;
                query->waiting_connect = ISC_FALSE;
+               query->pending_free = ISC_FALSE;
                query->recv_made = ISC_FALSE;
                query->first_pass = ISC_TRUE;
                query->first_soa_rcvd = ISC_FALSE;
@@ -2052,6 +2062,7 @@ send_done(isc_task_t *_task, isc_event_t *event) {
 
        query = event->ev_arg;
        l = query->lookup;
+       l->waiting_senddone = ISC_FALSE;
 
        if (l->ns_search_only && !l->trace_root) {
                debug("sending next, since searching");
@@ -2062,6 +2073,11 @@ send_done(isc_task_t *_task, isc_event_t *event) {
 
        isc_event_free(&event);
 
+       if (query->pending_free)
+               isc_mem_free(mctx, query);
+       if (l->pending_clear)
+               try_clear_lookup(l);
+
        check_if_done();
        UNLOCK_LOOKUP;
 }
@@ -2252,6 +2268,7 @@ send_udp(dig_query_t *query) {
        debug("sending a request");
        TIME_NOW(&query->time_sent);
        INSIST(query->sock != NULL);
+       l->waiting_senddone = ISC_TRUE;
        result = isc_socket_sendtov(query->sock, &query->sendlist,
                                    global_task, send_done, query,
                                    &query->sockaddr, NULL);
@@ -2451,6 +2468,7 @@ launch_next_query(dig_query_t *query, isc_boolean_t include_question) {
        if (!query->first_soa_rcvd) {
                debug("sending a request in launch_next_query");
                TIME_NOW(&query->time_sent);
+               query->lookup->waiting_senddone = ISC_TRUE;
                result = isc_socket_sendv(query->sock, &query->sendlist,
                                          global_task, send_done, query);
                check_result(result, "isc_socket_sendv");
index d97efc1e42962142871018c04d96fe49ce45e524..36da7f748b807c29dffd391f1155c6c2949af1a5 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: dig.h,v 1.98 2006/01/27 23:57:46 marka Exp $ */
+/* $Id: dig.h,v 1.99 2006/10/02 03:08:34 marka Exp $ */
 
 #ifndef DIG_H
 #define DIG_H
@@ -103,6 +103,8 @@ typedef struct dig_searchlist dig_searchlist_t;
 struct dig_lookup {
        isc_boolean_t
                pending, /*%< Pending a successful answer */
+               waiting_senddone,
+               pending_clear,
                waiting_connect,
                doing_xfr,
                ns_search_only, /*%< dig +nssearch, host -C */
@@ -186,6 +188,7 @@ isc_boolean_t       sigchase;
 struct dig_query {
        dig_lookup_t *lookup;
        isc_boolean_t waiting_connect,
+               pending_free,
                first_pass,
                first_soa_rcvd,
                second_rr_rcvd,