]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: listener: keep accept rate counters accurate under saturation
authorWilly Tarreau <w@1wt.eu>
Mon, 25 Feb 2019 14:02:04 +0000 (15:02 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 27 Feb 2019 07:03:41 +0000 (08:03 +0100)
The test on l->nbconn forces to exit the loop before updating the freq
counters, so the last session which reaches a listener's limit will not
be accounted for in the session rate measurement.

Let's move the test at the beginning of the loop and mark the listener
as saturated on exit.

This may be backported to 1.9 and 1.8.

src/listener.c

index 4d080310d1b8e1a27c4ab1e9ee18fe1a5e776089..f8745e33607fd8c78f9652305848eaef8dd40612 100644 (file)
@@ -464,11 +464,6 @@ void listener_accept(int fd)
        if (HA_SPIN_TRYLOCK(LISTENER_LOCK, &l->lock))
                return;
 
-       if (unlikely(l->nbconn >= l->maxconn)) {
-               listener_full(l);
-               goto end;
-       }
-
        if (!(l->options & LI_O_UNLIMITED) && global.sps_lim) {
                int max = freq_ctr_remain(&global.sess_per_sec, global.sps_lim, 0);
 
@@ -527,7 +522,7 @@ void listener_accept(int fd)
         * worst case. If we fail due to system limits or temporary resource
         * shortage, we try again 100ms later in the worst case.
         */
-       while (max_accept--) {
+       while (l->nbconn < l->maxconn && max_accept--) {
                struct sockaddr_storage addr;
                socklen_t laddr = sizeof(addr);
                unsigned int count;
@@ -647,11 +642,6 @@ void listener_accept(int fd)
                        goto transient_error;
                }
 
-               if (l->nbconn >= l->maxconn) {
-                       listener_full(l);
-                       goto end;
-               }
-
                /* increase the per-process number of cumulated connections */
                if (!(l->options & LI_O_UNLIMITED)) {
                        count = update_freq_ctr(&global.sess_per_sec, 1);
@@ -679,6 +669,9 @@ void listener_accept(int fd)
        limit_listener(l, &global_listener_queue);
        task_schedule(global_listener_queue_task, tick_first(expire, global_listener_queue_task->expire));
  end:
+       if (l->nbconn >= l->maxconn)
+               listener_full(l);
+
        HA_SPIN_UNLOCK(LISTENER_LOCK, &l->lock);
 }