]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: pools: Always update free_list in pool_gc().
authorOlivier Houchard <ohouchard@haproxy.com>
Thu, 12 Mar 2020 18:05:39 +0000 (19:05 +0100)
committerOlivier Houchard <cognet@ci0.org>
Thu, 12 Mar 2020 18:07:10 +0000 (19:07 +0100)
In pool_gc(), when we're not using lockless pool, always update free_list,
and read from it the next element to free. As we now unlock the pool while
we're freeing the item, another thread could have updated free_list in our
back. Not doing so could lead to segfaults when pool_gc() is called.

This should be backported to 2.1.

src/memory.c

index 0ff3ea8b8fae05819a6ff194f0912b8e90400947..b0512aaece5ddfc2a1f93086240243e2bc25021b 100644 (file)
@@ -429,15 +429,14 @@ void pool_gc(struct pool_head *pool_ctx)
                return;
 
        list_for_each_entry(entry, &pools, list) {
-               void *temp, *next;
+               void *temp;
                //qfprintf(stderr, "Flushing pool %s\n", entry->name);
                if (entry != pool_ctx)
                        HA_SPIN_LOCK(POOL_LOCK, &entry->lock);
-               next = entry->free_list;
-               while (next &&
+               while (entry->free_list &&
                       (int)(entry->allocated - entry->used) > (int)entry->minavail) {
-                       temp = next;
-                       next = *POOL_LINK(entry, temp);
+                       temp = entry->free_list;
+                       entry->free_list = *POOL_LINK(entry, temp);
                        entry->allocated--;
                        if (entry != pool_ctx)
                                HA_SPIN_UNLOCK(POOL_LOCK, &entry->lock);
@@ -445,7 +444,6 @@ void pool_gc(struct pool_head *pool_ctx)
                        if (entry != pool_ctx)
                                HA_SPIN_LOCK(POOL_LOCK, &entry->lock);
                }
-               entry->free_list = next;
                if (entry != pool_ctx)
                        HA_SPIN_UNLOCK(POOL_LOCK, &entry->lock);
        }