]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
fixup callbacks deletion.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 20 Jun 2007 09:52:32 +0000 (09:52 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Wed, 20 Jun 2007 09:52:32 +0000 (09:52 +0000)
git-svn-id: file:///svn/unbound/trunk@405 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
services/outside_network.c
services/outside_network.h

index 8504da85c25bdc8627e2f876ecbb4e394e9f0f3f..79a8a87dfaaacfa79813a04cc32cd323cba55d9d 100644 (file)
@@ -2,6 +2,7 @@
        - new -C option to enable coredumps after forking away.
        - doc update.
        - fixup CNAME generation by scrubber, and memory allocation of it.
+       - fixup deletion of serviced queries when all callbacks delete too.
 
 19 June 2007: Wouter
        - nicer layout in stats.c, review 0.3 change.
index e79a0f9133b54dd32d2e874527231fc9aee66365..ddd0759b965693c34adf6a90e058cd1c45956aac 100644 (file)
@@ -884,6 +884,7 @@ serviced_create(struct outside_network* outnet, ldns_buffer* buff, int dnssec,
        sq->pending = NULL;
        sq->status = serviced_initial;
        sq->retry = 0;
+       sq->to_be_deleted = 0;
        ins = rbtree_insert(outnet->serviced, &sq->node);
        log_assert(ins != NULL); /* must not be already present */
        return sq;
@@ -997,11 +998,19 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
        struct comm_reply* rep)
 {
        struct service_callback* p = sq->cblist, *n;
+       rbnode_t* rem;
+       /* remove from tree, and schedule for deletion, so that callbacks
+        * can safely deregister themselves and even create new serviced
+        * queries that are identical to this one. */
+       rem = rbtree_delete(sq->outnet->serviced, sq);
+       log_assert(rem); /* should have been present */
+       sq->to_be_deleted = 1; 
        while(p) {
                n = p->next;
                (void)(*p->cb)(c, p->cb_arg, error, rep);
                p = n;
        }
+       serviced_delete(sq);
 }
 
 /** TCP reply or error callback for serviced queries */
@@ -1030,9 +1039,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
        }
        memcpy(&rep->addr, &sq->addr, sq->addrlen);
        rep->addrlen = sq->addrlen;
-       (void)rbtree_delete(sq->outnet->serviced, sq);
        serviced_callbacks(sq, error, c, rep);
-       serviced_delete(sq);
        return 0;
 }
 
@@ -1048,9 +1055,7 @@ serviced_tcp_initiate(struct outside_network* outnet,
                /* delete from tree so that a retry by above layer does not
                 * clash with this entry */
                log_err("serviced_tcp_initiate: failed to send tcp query");
-               (void)rbtree_delete(outnet->serviced, sq);
                serviced_callbacks(sq, NETEVENT_CLOSED, NULL, NULL);
-               serviced_delete(sq);
        }
 }
 
@@ -1076,9 +1081,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
                        log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
                                &sq->addr, sq->addrlen);
                        if(!serviced_udp_send(sq, c->buffer)) {
-                               (void)rbtree_delete(outnet->serviced, sq);
                                serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
-                               serviced_delete(sq);
                        }
                        return 0;
                }
@@ -1096,9 +1099,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
                sq->status = serviced_query_UDP;
                sq->retry = 0;
                if(!serviced_udp_send(sq, c->buffer)) {
-                       (void)rbtree_delete(outnet->serviced, sq);
                        serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
-                       serviced_delete(sq);
                }
                return 0;
        }
@@ -1124,9 +1125,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
                        roundtime, (time_t)now.tv_sec))
                        log_err("out of memory noting rtt.");
        }
-       (void)rbtree_delete(outnet->serviced, sq);
        serviced_callbacks(sq, error, c, rep);
-       serviced_delete(sq);
        return 0;
 }
 
@@ -1209,8 +1208,11 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
        if(!sq) 
                return;
        callback_list_remove(sq, cb_arg);
-       if(!sq->cblist) {
-               if(rbtree_delete(sq->outnet->serviced, sq))
-                       serviced_delete(sq); /* safe against double delete */
+       /* if callbacks() routine scheduled deletion, let it do that */
+       if(!sq->cblist && !sq->to_be_deleted) {
+               rbnode_t* rem;
+               rem = rbtree_delete(sq->outnet->serviced, sq);
+               log_assert(rem); /* should be present */
+               serviced_delete(sq); 
        }
 }
index 13a2cd257eeb2aa0b10d759796e89ce794289248..6fc794e256ed1d07a652bd5a3e724053d0448e9c 100644 (file)
@@ -223,6 +223,8 @@ struct serviced_query {
                /** TCP without EDNS sent */
                serviced_query_TCP
        } status;
+       /** true if serviced_query is scheduled for deletion already */
+       int to_be_deleted;
        /** number of UDP retries */
        int retry;
        /** time last UDP was sent */