From a643baf09157656b0919d46c8b68a24fd5277589 Mon Sep 17 00:00:00 2001 From: Krzysztof Piotr Oledzki Date: Thu, 29 May 2008 23:53:44 +0200 Subject: [PATCH] [MEDIUM] Fix memory freeing at exit 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 | 3 +++ include/proto/fd.h | 5 +++++ include/types/server.h | 1 + src/acl.c | 16 ++++++++++++++++ src/appsession.c | 27 +++++++++++++++++---------- src/checks.c | 2 ++ src/fd.c | 16 ++++++++++++++++ src/haproxy.c | 32 +++++++++++++++++++++++++++----- src/memory.c | 2 ++ 9 files changed, 89 insertions(+), 15 deletions(-) diff --git a/include/proto/acl.h b/include/proto/acl.h index 4e2b30177..8b0c5e0a9 100644 --- a/include/proto/acl.h +++ b/include/proto/acl.h @@ -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 , then return . */ +struct acl *prune_acl(struct acl *acl); + /* Parse an ACL with the name starting at [0], and with a list of already * known ACLs in . If the ACL was not in the list, it will be added. * A pointer to that ACL is returned. diff --git a/include/proto/fd.h b/include/proto/fd.h index 74b04b29e..1cba33b7f 100644 --- a/include/proto/fd.h +++ b/include/proto/fd.h @@ -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, diff --git a/include/types/server.h b/include/types/server.h index 0e2183ef5..462db2b4f 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -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() */ diff --git a/src/acl.c b/src/acl.c index aa095c5bd..96b21de42 100644 --- 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 , then return . */ +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 [0], and with a list of already * known ACLs in . If the ACL was not in the list, it will be added. * A pointer to that ACL is returned. diff --git a/src/appsession.c b/src/appsession.c index 9b6868c3a..e1a01cc49 100644 --- a/src/appsession.c +++ b/src/appsession.c @@ -27,7 +27,7 @@ #include - +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() */ diff --git a/src/checks.c b/src/checks.c index 0b8756b8a..be26711e3 100644 --- a/src/checks.c +++ b/src/checks.c @@ -848,6 +848,8 @@ int start_checks() { return -1; } + s->check = t; + t->wq = NULL; t->qlist.p = NULL; t->state = TASK_IDLE; diff --git a/src/fd.c b/src/fd.c index 9c370faf9..eaaaabf50 100644 --- 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 . * Should be performed only before initialization. diff --git a/src/haproxy.c b/src/haproxy.c index b42728ecc..4b6bdf899 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -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 to all pids found in */ diff --git a/src/memory.c b/src/memory.c index b157cf0a0..2fe37662d 100644 --- a/src/memory.c +++ b/src/memory.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -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; } }