]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] Fix memory freeing at exit
authorKrzysztof Piotr Oledzki <ole@ans.pl>
Thu, 29 May 2008 21:53:44 +0000 (23:53 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 30 May 2008 05:07:19 +0000 (07:07 +0200)
New functions implemented:
 - deinit_pollers: called at the end of deinit())
 - prune_acl: called via list_for_each_entry_safe

Add missing pool_destroy2 calls:
 - p->hdr_idx_pool
 - pool2_tree64

Implement all task stopping:
 - health-check: needs new "struct task" in the struct server
 - queue processing: queue_mgt
 - appsess_refresh: appsession_refresh

before (idle system):
==6079== LEAK SUMMARY:
==6079==    definitely lost: 1,112 bytes in 75 blocks.
==6079==    indirectly lost: 53,356 bytes in 2,090 blocks.
==6079==      possibly lost: 52 bytes in 1 blocks.
==6079==    still reachable: 150,996 bytes in 504 blocks.
==6079==         suppressed: 0 bytes in 0 blocks.

after (idle system):
==6945== LEAK SUMMARY:
==6945==    definitely lost: 7,644 bytes in 137 blocks.
==6945==    indirectly lost: 9,913 bytes in 587 blocks.
==6945==      possibly lost: 0 bytes in 0 blocks.
==6945==    still reachable: 0 bytes in 0 blocks.
==6945==         suppressed: 0 bytes in 0 blocks.

before (running system for ~2m):
==9343== LEAK SUMMARY:
==9343==    definitely lost: 1,112 bytes in 75 blocks.
==9343==    indirectly lost: 54,199 bytes in 2,122 blocks.
==9343==      possibly lost: 52 bytes in 1 blocks.
==9343==    still reachable: 151,128 bytes in 509 blocks.
==9343==         suppressed: 0 bytes in 0 blocks.

after (running system for ~2m):
==11616== LEAK SUMMARY:
==11616==    definitely lost: 7,644 bytes in 137 blocks.
==11616==    indirectly lost: 9,981 bytes in 591 blocks.
==11616==      possibly lost: 0 bytes in 0 blocks.
==11616==    still reachable: 4 bytes in 1 blocks.
==11616==         suppressed: 0 bytes in 0 blocks.

Still not perfect but significant improvement.

include/proto/acl.h
include/proto/fd.h
include/types/server.h
src/acl.c
src/appsession.c
src/checks.c
src/fd.c
src/haproxy.c
src/memory.c

index 4e2b30177a0bf4b241b167f88a40e53ba826399f..8b0c5e0a9acc319102dbe01e1a1eb7d0045e715d 100644 (file)
@@ -47,6 +47,9 @@ struct acl_keyword *find_acl_kw(const char *kw);
  */
 struct acl_expr *parse_acl_expr(const char **args);
 
+/* Purge everything in the acl <acl>, then return <acl>. */
+struct acl *prune_acl(struct acl *acl);
+
 /* Parse an ACL with the name starting at <args>[0], and with a list of already
  * known ACLs in <acl>. If the ACL was not in the list, it will be added.
  * A pointer to that ACL is returned.
index 74b04b29edde78f245b2dc4689d28b84dfb1d8f9..1cba33b7f1edc913de1dbe0f12db2ddba3edef5d 100644 (file)
@@ -45,6 +45,11 @@ void disable_poller(const char *poller_name);
  */
 int init_pollers();
 
+/*
+ * Deinitialize the pollers.
+ */
+void deinit_pollers();
+
 /*
  * Some pollers may lose their connection after a fork(). It may be necessary
  * to create initialize part of them again. Returns 0 in case of failure,
index 0e2183ef57bd6170dca0893193458e541a4d502f..462db2b4f98eba352d25101a696206c0fc9a349f 100644 (file)
@@ -84,6 +84,7 @@ struct server {
        int maxqueue;                           /* maximum number of pending connections allowed */
        struct list pendconns;                  /* pending connections */
        struct task *queue_mgt;                 /* the task associated to the queue processing */
+       struct task *check;                     /* the task associated to the health check processing */
 
        struct sockaddr_in addr;                /* the address to connect to */
        struct sockaddr_in source_addr;         /* the address to which we want to bind for connect() */
index aa095c5bd2909a112bf73a8689de6e74a156b568..96b21de42bf3e7d6bc86295ca8629b34fc23fe3c 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -567,6 +567,22 @@ struct acl_expr *parse_acl_expr(const char **args)
        return NULL;
 }
 
+/* Purge everything in the acl <acl>, then return <acl>. */
+struct acl *prune_acl(struct acl *acl) {
+
+       struct acl_expr *expr, *exprb;
+
+       free(acl->name);
+
+       list_for_each_entry_safe(expr, exprb, &acl->expr, list) {
+               LIST_DEL(&expr->list);
+               prune_acl_expr(expr);
+               free(expr);
+       }
+
+       return acl;
+}
+
 /* Parse an ACL with the name starting at <args>[0], and with a list of already
  * known ACLs in <acl>. If the ACL was not in the list, it will be added.
  * A pointer to that ACL is returned.
index 9b6868c3ae08283a6e9e2243e07de4f418929267..e1a01cc49a8ba8503e4b8dc05b2e47ad78adac3f 100644 (file)
@@ -27,7 +27,7 @@
 
 #include <proto/task.h>
 
-
+static struct task *appsess_refresh = NULL;
 struct pool_head *pool2_appsess;
 struct app_pool apools;
 int have_appsession;
@@ -87,17 +87,17 @@ int appsession_init(void)
 int appsession_task_init(void)
 {
        static int initialized = 0;
-       struct task *t;
        if (!initialized) {
-               if ((t = pool_alloc2(pool2_task)) == NULL)
+               if ((appsess_refresh = pool_alloc2(pool2_task)) == NULL)
                        return -1;
-               t->wq = NULL;
-               t->qlist.p = NULL;
-               t->state = TASK_IDLE;
-               t->context = NULL;
-               tv_ms_add(&t->expire, &now, TBLCHKINT);
-               t->process = appsession_refresh;
-               task_queue(t);
+
+               appsess_refresh->wq = NULL;
+               appsess_refresh->qlist.p = NULL;
+               appsess_refresh->state = TASK_IDLE;
+               appsess_refresh->context = NULL;
+               tv_ms_add(&appsess_refresh->expire, &now, TBLCHKINT);
+               appsess_refresh->process = appsession_refresh;
+               task_queue(appsess_refresh);
                initialized ++;
        }
        return 0;
@@ -168,6 +168,13 @@ void appsession_cleanup( void )
                appsession_hash_destroy(&(p->htbl_proxy));
                p = p->next;
        }
+
+       if (appsess_refresh) {
+               task_delete(appsess_refresh);
+               task_free(appsess_refresh);
+               appsess_refresh = NULL;
+       }
+
 }/* end appsession_cleanup() */
 
 
index 0b8756b8a29c246be157d3fbd25927674fccf478..be26711e3d2809350961d956b2eb3700aeb5e134 100644 (file)
@@ -848,6 +848,8 @@ int start_checks() {
                                return -1;
                        }
 
+                       s->check = t;
+
                        t->wq = NULL;
                        t->qlist.p = NULL;
                        t->state = TASK_IDLE;
index 9c370faf93d7179b2e40a40f8eae05e849ee7f75..eaaaabf50b34322ecfa71b5e184d509559afd307 100644 (file)
--- a/src/fd.c
+++ b/src/fd.c
@@ -86,6 +86,22 @@ int init_pollers()
        return 0;
 }
 
+/*
+ * Deinitialize the pollers.
+ */
+void deinit_pollers() {
+
+       struct poller *bp;
+       int p;
+
+       for (p = 0; p < nbpollers; p++) {
+               bp = &pollers[p];
+
+               if (bp && bp->pref)
+                       bp->term(bp);
+       }
+}
+
 /*
  * Lists the known pollers on <out>.
  * Should be performed only before initialization.
index b42728eccbf3eeb59204e19c0177dcbbb49da57e..4b6bdf899a8b002230d40f9ed9cca80a1a3523ea 100644 (file)
@@ -646,6 +646,7 @@ void deinit(void)
        struct listener *l,*l_next;
        struct acl_cond *cond, *condb;
        struct hdr_exp *exp, *expb;
+       struct acl *acl, *aclb;
        int i;
   
        while (p) {
@@ -718,10 +719,15 @@ void deinit(void)
                }
 
                /* FIXME: this must also be freed :
-                *  - ACLs
                 *  - uri_auth (but it's shared)
                 */
 
+               list_for_each_entry_safe(acl, aclb, &p->acl, list) {
+                       LIST_DEL(&acl->list);
+                       prune_acl(acl);
+                       free(acl);
+               }
+
                if (p->appsession_name)
                        free(p->appsession_name);
 
@@ -745,10 +751,21 @@ void deinit(void)
                        free(h);
                        h = h_next;
                }/* end while(h) */
-       
+
                s = p->srv;
                while (s) {
                        s_next = s->next;
+
+                       if (s->check) {
+                               task_delete(s->check);
+                               task_free(s->check);
+                       }
+
+                       if (s->queue_mgt) {
+                               task_delete(s->queue_mgt);
+                               task_free(s->queue_mgt);
+                       }
+
                        if (s->id)
                                free(s->id);
            
@@ -758,16 +775,17 @@ void deinit(void)
                        free(s);
                        s = s_next;
                }/* end while(s) */
-       
+
                l = p->listen;
                while (l) {
                        l_next = l->next;
                        free(l);
                        l = l_next;
                }/* end while(l) */
-       
+
                pool_destroy2(p->req_cap_pool);
                pool_destroy2(p->rsp_cap_pool);
+               pool_destroy2(p->hdr_idx_pool);
                p0 = p;
                p = p->next;
                free(p0);
@@ -783,11 +801,12 @@ void deinit(void)
     
        if (fdtab)            free(fdtab);
        fdtab = NULL;
-    
+
        pool_destroy2(pool2_session);
        pool_destroy2(pool2_buffer);
        pool_destroy2(pool2_requri);
        pool_destroy2(pool2_task);
+       pool_destroy2(pool2_tree64);
        pool_destroy2(pool2_capture);
        pool_destroy2(pool2_appsess);
        pool_destroy2(pool2_pendconn);
@@ -796,6 +815,9 @@ void deinit(void)
                pool_destroy2(apools.serverid);
                pool_destroy2(apools.sessid);
        }
+
+       deinit_pollers();
+
 } /* end deinit() */
 
 /* sends the signal <sig> to all pids found in <oldpids> */
index b157cf0a06b5f732e0465cbb618bca447343267c..2fe37662d71cf702b2d5032f578ffca5627fa86e 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <common/config.h>
+#include <common/debug.h>
 #include <common/memory.h>
 #include <common/mini-clist.h>
 #include <common/standard.h>
@@ -51,6 +52,7 @@ struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags)
                        if (flags & entry->flags & MEM_F_SHARED) {
                                /* we can share this one */
                                pool = entry;
+                               DPRINTF(stderr, "Sharing %s with %s\n", name, pool->name);
                                break;
                        }
                }