From 3c84247622c7d6ad51e7a49907995e3e48b5f472 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 22 Feb 2016 20:39:45 +0100 Subject: [PATCH] resolved: fix notification iteration logic when transactions are completed When a transaction is complete, and we notify its owners, make sure we deal correctly with the requesters removing themselves from the list of owners while we continue iterating. This was previously already dealt with with transactions that require other transactions for DNSSEC purposes, fix this for other possibly transaction owners too now. Since iterating through "Set" objects is not safe regarding removal of entries from it, rework the logic to use two Sets, and move each entry we notified from one set to the other set before we dispatch the notification. This move operation requires no additional memory, and enables us to ensure that we don't notify any object twice. Fixes: #2676 --- src/basic/macro.h | 6 ++++++ src/basic/set.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/basic/macro.h b/src/basic/macro.h index 2695d0edb..ab5cc97e1 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -361,6 +361,12 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { _found; \ }) +#define SWAP_TWO(x, y) do { \ + typeof(x) _t = (x); \ + (x) = (y); \ + (y) = (_t); \ + } while (false) + /* Define C11 thread_local attribute even on older gcc compiler * version */ #ifndef thread_local diff --git a/src/basic/set.h b/src/basic/set.h index f8e86478c..170f0c446 100644 --- a/src/basic/set.h +++ b/src/basic/set.h @@ -130,6 +130,9 @@ int set_put_strdupv(Set *s, char **l); #define SET_FOREACH(e, s, i) \ for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); ) +#define SET_FOREACH_MOVE(e, d, s) \ + for (; ({ e = set_first(s); assert_se(!e || set_move_one(d, s, e) >= 0); e; }); ) + DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); -- 2.30.2