]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MAJOR: server: prevent deadlock when using 'set maxconn server'
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 17 May 2021 08:47:18 +0000 (10:47 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 19 May 2021 15:52:05 +0000 (17:52 +0200)
A deadlock is possible with 'set maxconn server' command, if there is
pending connection ready to be dequeued. This is caused by the locking
of server spinlock in both cli_parse_set_maxconn_server and
process_srv_queue.

Fix this by reducing the scope of the server lock into
server_parse_maxconn_change_request. If connection are dequeued, the
lock is taken a second time. This can be seen as suboptimal but as it
happens only during 'set maxconn server' it can be considered as
tolerable.

This issue was reported on the mailing list, for the 1.8.x branch.
It must be backported up to the 1.8.

src/server.c

index fa1d9d6c6e8e873e1316a535bf5aa876fb285bf1..49bd5450b73f8ece4c4d61db47eba639adb3d505 100644 (file)
@@ -1800,11 +1800,13 @@ const char *server_parse_maxconn_change_request(struct server *sv,
        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);
 
        if (may_dequeue_tasks(sv, sv->proxy))
                process_srv_queue(sv);
@@ -4141,14 +4143,10 @@ static int cli_parse_set_maxconn_server(char **args, char *payload, struct appct
        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;
 }