BUG/MEDIUM: queues: Stricly respect maxconn for outgoing connections

The "served" field of struct server is used to know how many connections
are currently in use for a server. But served used to be incremented way
after the server was picked, so there were race conditions that could
lead more than maxconn connections to be allocated for one server. To
fix this, increment served way earlier, and make sure at the time that
it never goes past maxconn.
We now should never have more outgoing connections than set by maxconn.
This commit is contained in:
Olivier Houchard
2024-12-17 13:30:46 +00:00
committed by Olivier Houchard
parent 4332fed6c1
commit 3372a2ea00
3 changed files with 74 additions and 23 deletions

View File

@@ -259,6 +259,9 @@ static int pendconn_process_next_strm(struct server *srv, struct proxy *px, int
struct pendconn *p = NULL;
struct pendconn *pp = NULL;
u32 pkey, ppkey;
int served;
int maxconn;
int got_it = 0;
p = NULL;
if (srv->queue.length)
@@ -277,7 +280,25 @@ static int pendconn_process_next_strm(struct server *srv, struct proxy *px, int
if (!p && !pp)
return 0;
else if (!pp)
served = _HA_ATOMIC_LOAD(&srv->served);
maxconn = srv_dynamic_maxconn(srv);
while (served < maxconn && !got_it)
got_it = _HA_ATOMIC_CAS(&srv->served, &served, served + 1);
/* No more slot available, give up */
if (!got_it) {
if (pp)
HA_SPIN_UNLOCK(QUEUE_LOCK, &px->queue.lock);
return 0;
}
/*
* Now we know we'll have something available.
* Let's try to allocate a slot on the server.
*/
if (!pp)
goto use_p; /* p != NULL */
else if (!p)
goto use_pp; /* pp != NULL */
@@ -394,10 +415,13 @@ int process_srv_queue(struct server *s)
HA_SPIN_LOCK(QUEUE_LOCK, &s->queue.lock);
while (s->served < maxconn) {
/*
* pendconn_process_next_strm() will increment
* the served field, only if it is < maxconn.
*/
stop = !pendconn_process_next_strm(s, p, px_ok);
if (stop)
break;
_HA_ATOMIC_INC(&s->served);
done++;
if (done >= global.tune.maxpollevents)
break;