BUG/MINOR: stats: use refcount to protect dynamic server on dump

A dynamic server may be deleted at runtime at the same moment when the
stats applet is pointing to it. Use the server refcount to prevent
deletion in this case.

This should be backported up to 2.4, with an observability period of 2
weeks. Note that it requires the dynamic server refcounting feature
which has been implemented on 2.5; the following commits are required :

- MINOR: server: implement a refcount for dynamic servers
- BUG/MINOR: server: do not use refcount in free_server in stopping mode
- MINOR: server: return the next srv instance on free_server
diff --git a/src/stats.c b/src/stats.c
index b767ce5..8140d87 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -3111,8 +3111,20 @@
 		/* fall through */
 
 	case STAT_PX_ST_SV:
-		/* obj2 points to servers list as initialized above */
-		for (; appctx->ctx.stats.obj2 != NULL; appctx->ctx.stats.obj2 = sv->next) {
+		/* obj2 points to servers list as initialized above.
+		 *
+		 * A dynamic server may be removed during the stats dumping.
+		 * Temporarily increment its refcount to prevent its
+		 * anticipated cleaning. Call free_server to release it.
+		 */
+		for (; appctx->ctx.stats.obj2 != NULL;
+		       appctx->ctx.stats.obj2 =
+		        (!(sv->flags & SRV_F_DYNAMIC)) ? sv->next : free_server(sv)) {
+
+			sv = appctx->ctx.stats.obj2;
+			if (sv->flags & SRV_F_DYNAMIC)
+				srv_use_dynsrv(sv);
+
 			if (htx) {
 				if (htx_almost_full(htx))
 					goto full;
@@ -3122,11 +3134,12 @@
 					goto full;
 			}
 
-			sv = appctx->ctx.stats.obj2;
-
 			if (appctx->ctx.stats.flags & STAT_BOUND) {
-				if (!(appctx->ctx.stats.type & (1 << STATS_TYPE_SV)))
+				if (!(appctx->ctx.stats.type & (1 << STATS_TYPE_SV))) {
+					if (sv->flags & SRV_F_DYNAMIC)
+						free_server(appctx->ctx.stats.obj2);
 					break;
+				}
 
 				if (appctx->ctx.stats.sid != -1 && sv->puid != appctx->ctx.stats.sid)
 					continue;