]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/queue: stop processing requests when a new request is queued 30764/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 4 Jan 2024 14:53:27 +0000 (23:53 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 4 Jan 2024 16:37:42 +0000 (01:37 +0900)
Otherwise, the loop triggers assertion:
```
Assertion 'e->p.b.key == i->next_key' failed at src/basic/hashmap.c:614, function hashmap_iterate_in_insertion_order(). Aborting.
```

src/network/networkd-manager.h
src/network/networkd-queue.c

index 3f3569f44d5a2e27f5824bc52ae8ba04ae47526d..a2edfd0e79c0c8c807bca728e1e243271b6e8f4a 100644 (file)
@@ -100,6 +100,7 @@ struct Manager {
 
         FirewallContext *fw_ctx;
 
+        bool request_queued;
         OrderedSet *request_queue;
 
         Hashmap *tuntap_fds_by_name;
index 7c6263096862b28da29970e893949fe2fb14f322..1678510d522950007028c6086c7d728677c65848 100644 (file)
@@ -168,6 +168,10 @@ static int request_new(
         if (req->counter)
                 (*req->counter)++;
 
+        /* If this is called in the ORDERED_SET_FOREACH() loop of manager_process_requests(), we need to
+         * exit from the loop, due to the limitation of the iteration on OrderedSet. */
+        manager->request_queued = true;
+
         if (ret)
                 *ret = req;
 
@@ -220,6 +224,8 @@ int manager_process_requests(Manager *manager) {
 
         assert(manager);
 
+        manager->request_queued = false;
+
         ORDERED_SET_FOREACH(req, manager->request_queue) {
                 _cleanup_(link_unrefp) Link *link = link_ref(req->link);
 
@@ -236,8 +242,11 @@ int manager_process_requests(Manager *manager) {
                         return 0;
 
                 r = req->process(req, link, req->userdata);
-                if (r == 0)
-                        continue; /* The request is not ready. */
+                if (r == 0) { /* The request is not ready. */
+                        if (manager->request_queued)
+                                break; /* a new request is queued during processing the request. */
+                        continue;
+                }
 
                 /* If the request sends netlink message, e.g. for Address or so, the Request object is
                  * referenced by the netlink slot, and will be detached later by its destroy callback.
@@ -251,6 +260,9 @@ int manager_process_requests(Manager *manager) {
                          * hence we need to exit from the loop. */
                         break;
                 }
+
+                if (manager->request_queued)
+                        break;
         }
 
         return 0;