BUG/MEDIUM: server: initialize the idle conns list after parsing the config

The idle conns lists are sized according to the number of threads. As such
they cannot be initialized during the parsing since nbthread can be set
later, as revealed by this simple config which randomly crashes when used.
Let's do this at the end instead.

    listen proxy
        bind :4445
        mode http
        timeout client 10s
        timeout server 10s
        timeout connect 10s
        http-reuse always
        server s1 127.0.0.1:8000

    global
        nbthread 8

This fix must be backported to 1.9 and 1.8.
This commit is contained in:
Willy Tarreau 2019-02-07 14:46:29 +01:00
parent b0769b2ed6
commit 835daa119e
2 changed files with 25 additions and 22 deletions

View File

@ -3543,6 +3543,31 @@ int check_config_validity()
/* update the mux */
newsrv->mux_proto = mux_ent;
}
/* initialize idle conns lists */
for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
int i;
newsrv->priv_conns = calloc(global.nbthread, sizeof(*newsrv->priv_conns));
newsrv->idle_conns = calloc(global.nbthread, sizeof(*newsrv->idle_conns));
newsrv->safe_conns = calloc(global.nbthread, sizeof(*newsrv->safe_conns));
if (!newsrv->priv_conns || !newsrv->idle_conns || !newsrv->safe_conns) {
free(srv->safe_conns); srv->safe_conns = NULL;
free(srv->idle_conns); srv->idle_conns = NULL;
free(srv->priv_conns); srv->priv_conns = NULL;
ha_alert("parsing [%s:%d] : failed to allocate idle connections for server '%s'.\n",
newsrv->conf.file, newsrv->conf.line, newsrv->id);
cfgerr++;
continue;
}
for (i = 0; i < global.nbthread; i++) {
LIST_INIT(&newsrv->priv_conns[i]);
LIST_INIT(&newsrv->idle_conns[i]);
LIST_INIT(&newsrv->safe_conns[i]);
}
}
}
/***********************************************************/

View File

@ -1713,7 +1713,6 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp
struct server *new_server(struct proxy *proxy)
{
struct server *srv;
int i;
srv = calloc(1, sizeof *srv);
if (!srv)
@ -1724,19 +1723,6 @@ struct server *new_server(struct proxy *proxy)
LIST_INIT(&srv->actconns);
srv->pendconns = EB_ROOT;
if ((srv->priv_conns = calloc(global.nbthread, sizeof(*srv->priv_conns))) == NULL)
goto free_srv;
if ((srv->idle_conns = calloc(global.nbthread, sizeof(*srv->idle_conns))) == NULL)
goto free_priv_conns;
if ((srv->safe_conns = calloc(global.nbthread, sizeof(*srv->safe_conns))) == NULL)
goto free_idle_conns;
for (i = 0; i < global.nbthread; i++) {
LIST_INIT(&srv->priv_conns[i]);
LIST_INIT(&srv->idle_conns[i]);
LIST_INIT(&srv->safe_conns[i]);
}
srv->next_state = SRV_ST_RUNNING; /* early server setup */
srv->last_change = now.tv_sec;
@ -1755,14 +1741,6 @@ struct server *new_server(struct proxy *proxy)
srv->max_reuse = -1;
return srv;
free_idle_conns:
free(srv->idle_conns);
free_priv_conns:
free(srv->priv_conns);
free_srv:
free(srv);
return NULL;
}
/*