BUG/MAJOR: server: fix deadlock when changing maxconn via agent-check

The server_parse_maxconn_change_request locks the server lock. However,
this function can be called via agent-checks or lua code which already
lock it. This bug has been introduced by the following commit :

  commit 79a88ba3d09f7e2b73ae27cb5d24cc087a548fa6
  BUG/MAJOR: server: prevent deadlock when using 'set maxconn server'

This commit tried to fix another deadlock with can occur because
previoulsy server_parse_maxconn_change_request requires the server lock
to be held. However, it may call internally process_srv_queue which also
locks the server lock. The locking policy has thus been updated. The fix
is functional for the CLI 'set maxconn' but fails to address the
agent-check / lua counterparts.

This new issue is fixed in two steps :
- changes from the above commit have been reverted. This means that
  server_parse_maxconn_change_request must again be called with the
  server lock.

- to counter the deadlock fixed by the above commit, process_srv_queue
  now takes an argument to render the server locking optional if the
  caller already held it. This is only used by
  server_parse_maxconn_change_request.

The above commit was subject to backport up to 1.8. Thus this commit
must be backported in every release where it is already present.

(cherry picked from commit 0274286dd3768c0d5e58588a1cb7e7e710fbc9d4)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit caaafd055edcbceb3d57ed9672b90900ec52a203)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/server.c b/src/server.c
index 3569fd1..b6092b1 100644
--- a/src/server.c
+++ b/src/server.c
@@ -1382,16 +1382,17 @@
 	else if (end[0] != '\0')
 		return "Trailing garbage in maxconn string";
 
-	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
 	if (sv->maxconn == sv->minconn) { // static maxconn
 		sv->maxconn = sv->minconn = v;
 	} else { // dynamic maxconn
 		sv->maxconn = v;
 	}
-	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
 
+	/* server_parse_maxconn_change_request requires the server lock held.
+	 * Specify it to process_srv_queue to prevent a deadlock.
+	 */
 	if (may_dequeue_tasks(sv, sv->proxy))
-		process_srv_queue(sv);
+		process_srv_queue(sv, 1);
 
 	return NULL;
 }
@@ -4638,10 +4639,14 @@
 	if (!sv)
 		return 1;
 
+	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
+
 	warning = server_parse_maxconn_change_request(sv, args[4]);
 	if (warning)
 		cli_err(appctx, warning);
 
+	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
+
 	return 1;
 }