]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
in outnet_tcptimer: pick up callbacks and clean the struct pending for
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 9 Jul 2020 08:28:47 +0000 (10:28 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 9 Jul 2020 08:28:47 +0000 (10:28 +0200)
use again in tcp_free list; then perform the callbacks in a cleaner state
for reentry into the outside network code.  Delete callbacks afterwards.

services/outside_network.c

index 8da5eeb64dd48240112716b902160b2304baf8c7..9c3c6ff8a4ec4c1526364f6931d3cee11fed22dc 100644 (file)
@@ -1773,6 +1773,7 @@ outnet_tcptimer(void* arg)
        } else {
                /* it was in use */
                struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting;
+               struct pending_tcp pickup;
                /* see if it needs unlink from reuse tree */
                if(pend->reuse.node.key) {
                        reuse_tcp_remove_tree_list(outnet, &pend->reuse);
@@ -1785,19 +1786,33 @@ outnet_tcptimer(void* arg)
 #endif
                }
                comm_point_close(pend->c);
+               /* pickup the callback items and call them after we have
+                * removed the current pending. so that the callbacks
+                * to the state machine happen after the query has timeouted
+                * and been deleted and it works from that clean state,
+                * because it may call the outside network routines to make
+                * new queries. */
+               pickup = *pend;
+               /* unlink them from pend, delete from pickup calls later */
+               pend->query = NULL;
+               rbtree_init(&pend->reuse.tree_by_id, reuse_id_cmp);
+               pend->reuse.write_wait_first = NULL;
+               pend->reuse.write_wait_last = NULL;
+               /* pend is clear for reuse in the tcp_free list */
+               pend->next_free = outnet->tcp_free;
+               outnet->tcp_free = pend;
+
                /* do failure callbacks for all the queries in the
                 * wait for write list and in the id-tree */
                /* callback for 'w' arg already in list of curquery,
                 * readwait list, writewait list */
-               reuse_cb_curquery_for_failure(pend, NETEVENT_TIMEOUT);
-               reuse_cb_readwait_for_failure(pend, NETEVENT_TIMEOUT);
-               reuse_cb_writewait_for_failure(pend, NETEVENT_TIMEOUT);
-               waiting_tcp_delete(pend->query); /* del curquery */
-               reuse_del_readwait(pend);
-               reuse_del_writewait(pend);
-               pend->query = NULL;
-               pend->next_free = outnet->tcp_free;
-               outnet->tcp_free = pend;
+               reuse_cb_curquery_for_failure(&pickup, NETEVENT_TIMEOUT);
+               reuse_cb_readwait_for_failure(&pickup, NETEVENT_TIMEOUT);
+               reuse_cb_writewait_for_failure(&pickup, NETEVENT_TIMEOUT);
+               /* delete the stored callback structures */
+               waiting_tcp_delete(pickup.query);
+               reuse_del_readwait(&pickup);
+               reuse_del_writewait(&pickup);
        }
        use_free_buffer(outnet);
 }