]> git.kaiwu.me - haproxy.git/commitdiff
DEBUG/MEDIUM: memory: optionally protect free data in pools
authorWilly Tarreau <w@1wt.eu>
Wed, 28 Oct 2015 14:09:29 +0000 (15:09 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 28 Oct 2015 14:27:59 +0000 (15:27 +0100)
When debugging a core file, it's sometimes convenient to be able to
visit the released entries in the pools (typically last released
session). Unfortunately the first bytes of these entries are destroyed
by the link elements of the pool. And of course, most structures have
their most accessed elements at the beginning of the structure (typically
flags). Let's add a build-time option DEBUG_MEMORY_POOLS which allocates
an extra pointer in each pool to put the link at the end of each pool
item instead of the beginning.

include/common/memory.h
src/memory.c

index af4e6534bff7c6c42e2a8d04e5d36a0ee993e5bd..bbac58d49a111cc3a78b584592443ca2d0caa2fb 100644 (file)
 #define MEM_F_SHARED   0
 #endif
 
+/* reserve an extra void* at the end of a pool for linking */
+#ifdef DEBUG_MEMORY_POOLS
+#define POOL_EXTRA (sizeof(void *))
+#define POOL_LINK(pool, item) (void **)(((char *)item) + (pool->size))
+#else
+#define POOL_EXTRA (0)
+#define POOL_LINK(pool, item) ((void **)(item))
+#endif
+
 struct pool_head {
        void **free_list;
        struct list list;       /* list of all known pools */
@@ -113,7 +122,7 @@ static inline void *pool_get_first(struct pool_head *pool)
        void *p;
 
        if ((p = pool->free_list) != NULL) {
-               pool->free_list = *(void **)pool->free_list;
+               pool->free_list = *POOL_LINK(pool, p);
                pool->used++;
        }
        return p;
@@ -162,7 +171,7 @@ static inline void *pool_alloc2(struct pool_head *pool)
 static inline void pool_free2(struct pool_head *pool, void *ptr)
 {
         if (likely(ptr != NULL)) {
-                *(void **)ptr= (void *)pool->free_list;
+               *POOL_LINK(pool, ptr) = (void *)pool->free_list;
                 pool->free_list = (void *)ptr;
                 pool->used--;
        }
index d9cef64b6e6944780d29a802e33c77fa051d8917..0363f36d8fb965497df6cb71d3f67b04f68f98f5 100644 (file)
@@ -33,14 +33,16 @@ struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
        struct list *start;
        unsigned int align;
 
-       /* We need to store at least a (void *) in the chunks. Since we know
+       /* We need to store a (void *) at the end of the chunks. Since we know
         * that the malloc() function will never return such a small size,
         * let's round the size up to something slightly bigger, in order to
         * ease merging of entries. Note that the rounding is a power of two.
+        * This extra (void *) is not accounted for in the size computation
+        * so that the visible parts outside are not affected.
         */
 
        align = 16;
-       size  = (size + align - 1) & -align;
+       size  = ((size + POOL_EXTRA + align - 1) & -align) - POOL_EXTRA;
 
        start = &pools;
        pool = NULL;
@@ -99,7 +101,7 @@ void *pool_refill_alloc(struct pool_head *pool, unsigned int avail)
                if (pool->limit && pool->allocated >= pool->limit)
                        return NULL;
 
-               ptr = MALLOC(pool->size);
+               ptr = MALLOC(pool->size + POOL_EXTRA);
                if (!ptr) {
                        if (failed)
                                return NULL;
@@ -110,7 +112,7 @@ void *pool_refill_alloc(struct pool_head *pool, unsigned int avail)
                if (++pool->allocated > avail)
                        break;
 
-               *(void **)ptr = (void *)pool->free_list;
+               *POOL_LINK(pool, ptr) = (void *)pool->free_list;
                pool->free_list = ptr;
        }
        pool->used++;
@@ -129,7 +131,7 @@ void pool_flush2(struct pool_head *pool)
        next = pool->free_list;
        while (next) {
                temp = next;
-               next = *(void **)temp;
+               next = *POOL_LINK(pool, temp);
                pool->allocated--;
                FREE(temp);
        }
@@ -158,7 +160,7 @@ void pool_gc2()
                while (next &&
                       (int)(entry->allocated - entry->used) > (int)entry->minavail) {
                        temp = next;
-                       next = *(void **)temp;
+                       next = *POOL_LINK(entry, temp);
                        entry->allocated--;
                        FREE(temp);
                }