BUG/MEDIUM: server: initialize the orphaned conns lists and tasks at the end

This also depends on the nbthread count, so it must only be performed after
parsing the whole config file. As a side effect, this removes some code
duplication between servers and server-templates.

This must be backported to 1.9.
diff --git a/include/proto/server.h b/include/proto/server.h
index 7aa09e4..fa36e8d 100644
--- a/include/proto/server.h
+++ b/include/proto/server.h
@@ -58,6 +58,7 @@
 int snr_resolution_cb(struct dns_requester *requester, struct dns_nameserver *nameserver);
 int snr_resolution_error_cb(struct dns_requester *requester, int error_code);
 struct server *snr_check_ip_callback(struct server *srv, void *ip, unsigned char *ip_family);
+struct task *srv_cleanup_idle_connections(struct task *task, void *ctx, unsigned short state);
 
 /* increase the number of cumulated connections on the designated server */
 static void inline srv_inc_sess_ctr(struct server *s)
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 44eac17..1afb49c 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -3553,9 +3553,9 @@
 			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;
+				free(newsrv->safe_conns); newsrv->safe_conns = NULL;
+				free(newsrv->idle_conns); newsrv->idle_conns = NULL;
+				free(newsrv->priv_conns); newsrv->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++;
@@ -3567,6 +3567,27 @@
 				LIST_INIT(&newsrv->idle_conns[i]);
 				LIST_INIT(&newsrv->safe_conns[i]);
 			}
+
+			if (newsrv->max_idle_conns != 0) {
+				newsrv->idle_orphan_conns = calloc(global.nbthread, sizeof(*newsrv->idle_orphan_conns));
+				newsrv->idle_task         = calloc(global.nbthread, sizeof(*newsrv->idle_task));
+				if (!newsrv->idle_orphan_conns || !newsrv->idle_task)
+					goto err;
+				for (i = 0; i < global.nbthread; i++) {
+					LIST_INIT(&newsrv->idle_orphan_conns[i]);
+					newsrv->idle_task[i] = task_new(1 << i);
+					if (!newsrv->idle_task[i])
+						goto err;
+					newsrv->idle_task[i]->process = srv_cleanup_idle_connections;
+					newsrv->idle_task[i]->context = newsrv;
+				}
+				continue;
+			err:
+				ha_alert("parsing [%s:%d] : failed to allocate idle connection tasks for server '%s'.\n",
+					 newsrv->conf.file, newsrv->conf.line, newsrv->id);
+				cfgerr++;
+				continue;
+			}
 		}
 	}
 
diff --git a/src/server.c b/src/server.c
index 86137f3..312aa19 100644
--- a/src/server.c
+++ b/src/server.c
@@ -50,7 +50,6 @@
 static void srv_update_state(struct server *srv, int version, char **params);
 static int srv_apply_lastaddr(struct server *srv, int *err_code);
 static int srv_set_fqdn(struct server *srv, const char *fqdn, int dns_locked);
-static struct task *cleanup_idle_connections(struct task *task, void *ctx, unsigned short state);
 
 /* List head of all known server keywords */
 static struct srv_kw_list srv_keywords = {
@@ -1938,25 +1937,6 @@
 		px->srv_act++;
 	srv_lb_commit_status(srv);
 
-	if (srv->max_idle_conns != 0) {
-		int i;
-
-		srv->idle_orphan_conns = calloc(global.nbthread, sizeof(*srv->idle_orphan_conns));
-		if (!srv->idle_orphan_conns)
-			goto err;
-		srv->idle_task = calloc(global.nbthread, sizeof(*srv->idle_task));
-		if (!srv->idle_task)
-			goto err;
-		for (i = 0; i < global.nbthread; i++) {
-			LIST_INIT(&srv->idle_orphan_conns[i]);
-			srv->idle_task[i] = task_new(1 << i);
-			if (!srv->idle_task[i])
-				goto err;
-			srv->idle_task[i]->process = cleanup_idle_connections;
-			srv->idle_task[i]->context = srv;
-		}
-	}
-
 	return 0;
 err:
 	return ERR_ALERT | ERR_FATAL;
@@ -2043,24 +2023,6 @@
 		/* Linked backwards first. This will be restablished after parsing. */
 		newsrv->next = px->srv;
 		px->srv = newsrv;
-		if (newsrv->max_idle_conns != 0) {
-			int i;
-
-			newsrv->idle_orphan_conns = calloc(global.nbthread, sizeof(*newsrv->idle_orphan_conns));
-			if (!newsrv->idle_orphan_conns)
-				goto err;
-			newsrv->idle_task = calloc(global.nbthread, sizeof(*newsrv->idle_task));
-			if (!newsrv->idle_task)
-				goto err;
-			for (i = 0; i < global.nbthread; i++) {
-				LIST_INIT(&newsrv->idle_orphan_conns[i]);
-				newsrv->idle_task[i] = task_new(1 << i);
-				if (!newsrv->idle_task[i])
-					goto err;
-				newsrv->idle_task[i]->process = cleanup_idle_connections;
-				newsrv->idle_task[i]->context = newsrv;
-			}
-		}
 	}
 	srv_set_id_from_prefix(srv, srv->tmpl_info.prefix, srv->tmpl_info.nb_low);
 
@@ -5343,7 +5305,7 @@
 	*s->adm_st_chg_cause = 0;
 }
 
-static struct task *cleanup_idle_connections(struct task *task, void *context, unsigned short state)
+struct task *srv_cleanup_idle_connections(struct task *task, void *context, unsigned short state)
 {
 	struct server *srv = context;
 	struct connection *conn, *conn_back;