MEDIUM: proxy: add the global frontend to the list of normal proxies

Since recent changes on the global frontend, it was not possible anymore
to soft-reload a process which had a stats socket because the socket would
not be disabled upon reload. The only solution to this endless madness is
to have the global frontend part of normal proxies.

Since we don't want to get an ID that shifts all other proxies and causes
trouble in deployed environments, we assign it ID #0 which other proxies
can't grab, and we don't report it in the stats pages.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index bc9d93f..a3f9c96 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -5690,7 +5690,7 @@
 		struct listener *listener;
 		unsigned int next_id;
 
-		if (!curproxy->uuid) {
+		if (curproxy->uuid < 0) {
 			/* proxy ID not set, use automatic numbering with first
 			 * spare entry starting with next_pxid.
 			 */
@@ -6512,7 +6512,8 @@
 		}
 
 		if (curproxy->cap & PR_CAP_FE) {
-			curproxy->accept = frontend_accept;
+			if (!curproxy->accept)
+				curproxy->accept = frontend_accept;
 
 			if (curproxy->tcp_req.inspect_delay ||
 			    !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
diff --git a/src/dumpstats.c b/src/dumpstats.c
index c8b60a6..0776121 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -160,7 +160,8 @@
 		return NULL;
 
 	init_new_proxy(fe);
-
+	fe->next = proxy;
+	proxy = fe;
 	fe->last_change = now.tv_sec;
 	fe->id = strdup("GLOBAL");
 	fe->cap = PR_CAP_FE;
@@ -169,6 +170,10 @@
 	fe->conf.file = strdup(file);
 	fe->conf.line = line;
 	fe->accept = stats_accept;
+
+	/* the stats frontend is the only one able to assign ID #0 */
+	fe->conf.id.key = fe->uuid = 0;
+	eb32_insert(&used_proxy_id, &fe->conf.id);
 	return fe;
 }
 
@@ -1709,8 +1714,8 @@
 		if (si->applet.ctx.stats.flags & STAT_SHOW_STAT) {
 			while (si->applet.ctx.stats.px) {
 				px = si->applet.ctx.stats.px;
-				/* skip the disabled proxies and non-networked ones */
-				if (px->state != PR_STSTOPPED &&
+				/* skip the disabled proxies, global frontend and non-networked ones */
+				if (px->state != PR_STSTOPPED && px->uuid > 0 &&
 				    (px->cap & (PR_CAP_FE | PR_CAP_BE))) {
 					if (stats_dump_proxy(si, px, NULL) == 0)
 						return 0;
@@ -2176,8 +2181,8 @@
 			if (buffer_almost_full(&rep->buf))
 				return 0;
 			px = si->applet.ctx.stats.px;
-			/* skip the disabled proxies and non-networked ones */
-			if (px->state != PR_STSTOPPED && (px->cap & (PR_CAP_FE | PR_CAP_BE)))
+			/* skip the disabled proxies, global frontend and non-networked ones */
+			if (px->state != PR_STSTOPPED && px->uuid > 0 && (px->cap & (PR_CAP_FE | PR_CAP_BE)))
 				if (stats_dump_proxy(si, px, uri) == 0)
 					return 0;
 
diff --git a/src/proxy.c b/src/proxy.c
index 820be2f..2c710bb 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -96,17 +96,17 @@
 
 	*sv = NULL;
 
-	pid = 0;
+	pid = -1;
 	if (*bk_name == '#')
 		pid = atoi(bk_name + 1);
-	sid = 0;
+	sid = -1;
 	if (*sv_name == '#')
 		sid = atoi(sv_name + 1);
 
 	for (p = proxy; p; p = p->next)
 		if ((p->cap & PR_CAP_BE) &&
-		    ((pid && p->uuid == pid) ||
-		     (!pid && strcmp(p->id, bk_name) == 0)))
+		    ((pid >= 0 && p->uuid == pid) ||
+		     (pid < 0 && strcmp(p->id, bk_name) == 0)))
 			break;
 	if (bk)
 		*bk = p;
@@ -320,15 +320,15 @@
 struct proxy *findproxy(const char *name, int cap) {
 
 	struct proxy *curproxy, *target = NULL;
-	int pid = 0;
+	int pid = -1;
 
 	if (*name == '#')
 		pid = atoi(name + 1);
 
 	for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
 		if ((curproxy->cap & cap) != cap ||
-		    (pid && curproxy->uuid != pid) ||
-		    (!pid && strcmp(curproxy->id, name)))
+		    (pid >= 0 && curproxy->uuid != pid) ||
+		    (pid < 0 && strcmp(curproxy->id, name)))
 			continue;
 
 		if (!target) {
@@ -451,6 +451,9 @@
 	/* Timeouts are defined as -1 */
 	proxy_reset_timeouts(p);
 	p->tcp_rep.inspect_delay = TICK_ETERNITY;
+
+	/* initial uuid is unassigned (-1) */
+	p->uuid = -1;
 }
 
 /*