From 07e9e64a3415e7398cebd50abec3378c2897ad77 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 17 Aug 2010 21:48:17 +0200 Subject: [PATCH] [BUG] stats: global stats timeout may be specified before stats socket. If the global stats timeout statement was found before the stats socket (or without), the parser would crash because the stats frontend was not initialized. Now we have an allocation function which solves the issue. This bug was introduced with 1.4 so it does not need backporting. (was commit 1c5819d2498ae3643c3880507847f948a53d2773 in 1.4) --- src/dumpstats.c | 60 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/dumpstats.c b/src/dumpstats.c index f8ba702e3..aa5b02f0e 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -110,6 +110,36 @@ int stats_accept(struct session *s) return 1; } +/* allocate a new stats frontend named , and return it + * (or NULL in case of lack of memory). + */ +static struct proxy *alloc_stats_fe(const char *name) +{ + struct proxy *fe; + + fe = (struct proxy *)calloc(1, sizeof(struct proxy)); + if (!fe) + return NULL; + + LIST_INIT(&fe->pendconns); + LIST_INIT(&fe->acl); + LIST_INIT(&fe->block_cond); + LIST_INIT(&fe->redirect_rules); + LIST_INIT(&fe->mon_fail_cond); + LIST_INIT(&fe->switching_rules); + LIST_INIT(&fe->tcp_req.inspect_rules); + + /* Timeouts are defined as -1, so we cannot use the zeroed area + * as a default value. + */ + proxy_reset_timeouts(fe); + + fe->last_change = now.tv_sec; + fe->id = strdup("GLOBAL"); + fe->cap = PR_CAP_FE; + return fe; +} + /* This function parses a "stats" statement in the "global" section. It returns * -1 if there is any error, otherwise zero. If it returns -1, it may write an * error message into ther buffer, for at most bytes, trailing @@ -140,28 +170,11 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx memcpy(&global.stats_sock.addr, &su, sizeof(su)); // guaranteed to fit if (!global.stats_fe) { - if ((global.stats_fe = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) { + if ((global.stats_fe = alloc_stats_fe("GLOBAL")) == NULL) { snprintf(err, errlen, "out of memory"); return -1; } - - LIST_INIT(&global.stats_fe->pendconns); - LIST_INIT(&global.stats_fe->acl); - LIST_INIT(&global.stats_fe->block_cond); - LIST_INIT(&global.stats_fe->redirect_rules); - LIST_INIT(&global.stats_fe->mon_fail_cond); - LIST_INIT(&global.stats_fe->switching_rules); - LIST_INIT(&global.stats_fe->tcp_req.inspect_rules); - - /* Timeouts are defined as -1, so we cannot use the zeroed area - * as a default value. - */ - proxy_reset_timeouts(global.stats_fe); - - global.stats_fe->last_change = now.tv_sec; - global.stats_fe->id = strdup("GLOBAL"); - global.stats_fe->cap = PR_CAP_FE; - global.stats_fe->maxconn = global.stats_sock.maxconn; + global.stats_fe->timeout.client = MS_TO_TICKS(10000); /* default timeout of 10 seconds */ } global.stats_sock.state = LI_INIT; @@ -173,8 +186,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx global.stats_sock.nice = -64; /* we want to boost priority for local stats */ global.stats_sock.frontend = global.stats_fe; global.stats_sock.perm.ux.level = ACCESS_LVL_OPER; /* default access level */ - - global.stats_fe->timeout.client = MS_TO_TICKS(10000); /* default timeout of 10 seconds */ + global.stats_fe->maxconn = global.stats_sock.maxconn; global.stats_sock.timeout = &global.stats_fe->timeout.client; global.stats_sock.next = global.stats_fe->listen; @@ -251,6 +263,12 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx snprintf(err, errlen, "a positive value is expected for 'stats timeout' in 'global section'"); return -1; } + if (!global.stats_fe) { + if ((global.stats_fe = alloc_stats_fe("GLOBAL")) == NULL) { + snprintf(err, errlen, "out of memory"); + return -1; + } + } global.stats_fe->timeout.client = MS_TO_TICKS(timeout); } else if (!strcmp(args[0], "maxconn")) {