From 4d2d098ea3b41d88a9559fa52dc2bf84071c5cc3 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 14 May 2007 00:39:29 +0200 Subject: [PATCH] [MAJOR] call garbage collector when doing soft stop When we're interrupted by another instance, it is very likely that the other one will need some memory. Now we know how to free what is not used, so let's do it. Also only free non-null pointers. Previously, pool_destroy() did implicitly check for this case which was incidentely needed. --- include/common/memory.h | 2 +- src/haproxy.c | 8 +++++++- src/memory.c | 13 ++++++++++--- src/proxy.c | 3 +++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/common/memory.h b/include/common/memory.h index 66f789e25..835d79df0 100644 --- a/include/common/memory.h +++ b/include/common/memory.h @@ -160,7 +160,7 @@ void pool_gc2(); * This function destroys a pull by freeing it completely. * This should be called only under extreme circumstances. */ -void pool_destroy2(struct pool_head *pool); +void *pool_destroy2(struct pool_head *pool); /* * Returns a pointer to type taken from the diff --git a/src/haproxy.c b/src/haproxy.c index 4e22e1920..a86abeb31 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -203,6 +203,7 @@ void usage(char *name) void sig_soft_stop(int sig) { soft_stop(); + pool_gc2(); signal(sig, SIG_IGN); } @@ -212,6 +213,7 @@ void sig_soft_stop(int sig) void sig_pause(int sig) { pause_proxies(); + pool_gc2(); signal(sig, sig_pause); } @@ -318,6 +320,7 @@ void sig_int(int sig) 0 GRACE time */ fast_stop(); + pool_gc2(); /* If we are killed twice, we decide to die*/ signal(sig, SIG_DFL); } @@ -330,6 +333,7 @@ void sig_term(int sig) 0 GRACE time */ fast_stop(); + pool_gc2(); /* If we are killed twice, we decide to die*/ signal(sig, SIG_DFL); } @@ -580,7 +584,7 @@ void init(int argc, char **argv) void deinit(void) { - struct proxy *p = proxy; + struct proxy *p = proxy, *p0; struct cap_hdr *h,*h_next; struct server *s,*s_next; struct listener *l,*l_next; @@ -654,7 +658,9 @@ void deinit(void) pool_destroy2(p->req_cap_pool); pool_destroy2(p->rsp_cap_pool); + p0 = p; p = p->next; + free(p0); }/* end while(p) */ if (global.chroot) free(global.chroot); diff --git a/src/memory.c b/src/memory.c index 589d1d270..800922714 100644 --- a/src/memory.c +++ b/src/memory.c @@ -103,6 +103,9 @@ void *pool_refill_alloc(struct pool_head *pool) void pool_flush2(struct pool_head *pool) { void *temp, *next; + if (!pool) + return; + next = pool->free_list; while (next) { temp = next; @@ -141,11 +144,15 @@ void pool_gc2() /* * This function destroys a pull by freeing it completely. * This should be called only under extreme circumstances. + * It always returns NULL, easing the clearing of the old pointer. */ -void pool_destroy2(struct pool_head *pool) +void *pool_destroy2(struct pool_head *pool) { - pool_flush2(pool); - FREE(pool); + if (pool) { + pool_flush2(pool); + FREE(pool); + } + return NULL; } /* Dump statistics on pools usage. diff --git a/src/proxy.c b/src/proxy.c index dd7f993e3..7d4b2ec08 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -230,6 +231,8 @@ void maintain_proxies(struct timeval *next) listeners--; } p->state = PR_STSTOPPED; + /* try to free more memory */ + pool_gc2(); } else { tv_bound(next, &p->stop_time);