]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Do not re-add a node to the same prunenodes list
authorMichał Kępień <michal@isc.org>
Fri, 1 Mar 2024 17:12:37 +0000 (18:12 +0100)
committerMichał Kępień <michal@isc.org>
Fri, 1 Mar 2024 17:12:37 +0000 (18:12 +0100)
If a node cleaned up by prune_tree() happens to belong to the same node
bucket as its parent, the latter is directly appended to the prunenodes
list currently processed by prune_tree().  However, the relevant code
branch does not account for the fact that the parent might already be on
the list it is trying to append it to.  Fix by only calling
ISC_LIST_APPEND() for parent nodes not yet added to their relevant
prunenodes list.

lib/dns/rbtdb.c

index 9d1b4cd372c581d0803240060a7719199728f2b0..38e697769ea4d30c87b462f0ae6839da1e7c1465 100644 (file)
@@ -2336,14 +2336,18 @@ prune_tree(isc_task_t *task, isc_event_t *event) {
 
                if (parent->locknum == locknum) {
                        /*
-                        * Add the parent to the matching prunenodes list
-                        * manually, because send_to_prune_tree() would create
-                        * new event in the case the current node was the last
-                        * node on the prunenodes list.
+                        * The parent belongs to the same node bucket as the
+                        * node we just processed, so there is no need to
+                        * switch node locks.  Directly add the parent to the
+                        * prunenodes list we are currently processing (unless
+                        * the parent is already on that list).
                         */
-                       new_reference(rbtdb, parent, isc_rwlocktype_write);
-                       ISC_LIST_APPEND(rbtdb->prunenodes[parent->locknum],
-                                       parent, prunelink);
+                       if (!ISC_LINK_LINKED(node, prunelink)) {
+                               new_reference(rbtdb, parent,
+                                             isc_rwlocktype_write);
+                               ISC_LIST_APPEND(rbtdb->prunenodes[locknum],
+                                               parent, prunelink);
+                       }
                        NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
                                    isc_rwlocktype_write);
                } else {