[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.
This commit is contained in:
Krzysztof Piotr Oledzki 2008-05-29 23:53:44 +02:00 committed by Willy Tarreau
parent 1acf217366
commit a643baf091
9 changed files with 89 additions and 15 deletions

View 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.

View 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,

View 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() */

View File

@ -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.

View 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() */

View File

@ -848,6 +848,8 @@ int start_checks() {
return -1;
}
s->check = t;
t->wq = NULL;
t->qlist.p = NULL;
t->state = TASK_IDLE;

View File

@ -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.

View 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);
@ -749,6 +755,17 @@ void deinit(void)
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);
@ -768,6 +785,7 @@ void deinit(void)
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);
@ -788,6 +806,7 @@ void deinit(void)
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> */

View 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;
}
}