]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: listener: Don't decrease actconn twice when a new session is rejected
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 23 Mar 2018 14:11:55 +0000 (15:11 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 23 Mar 2018 15:21:50 +0000 (16:21 +0100)
When a freshly created session is rejected, for any reason, during the accept in
the function "session_accept_fd", the variable "actconn" is decreased twice. The
first time when the rejected session is released, then in the function
"listener_accpect", because of the failure. So it is possible to have an
negative value for actconn. Note that, in this case, we will also have a negatve
value for the current number of connections on the listener rejecting the
session (actconn and l->nbconn are in/decreased in same time).

It is easy to reproduce the bug with this small configuration:

  global
      stats socket /tmp/haproxy

  listen test
      bind *:12345
      tcp-request connection reject if TRUE

A "show info" on the stat socket, after a connection attempt, will show a very
high value (the unsigned representation of -1).

To fix the bug, if the function "session_accept_fd" returns an error, it
decrements the right counters and "listener_accpect" leaves them untouched.

This patch must be backported in 1.8.

src/listener.c
src/session.c

index 283058ace46d848ee4b05d9cb3a5cb902ef0dd96..20244056f06dcdec9d75f6b553e891039816315e 100644 (file)
@@ -617,9 +617,6 @@ void listener_accept(int fd)
                         * error due to a resource shortage, and we must stop the
                         * listener (ret < 0).
                         */
-                       if (!(l->options & LI_O_UNLIMITED))
-                               HA_ATOMIC_SUB(&actconn, 1);
-                       HA_ATOMIC_SUB(&l->nbconn, 1);
                        if (ret == 0) /* successful termination */
                                continue;
 
index ae98c9476d8b2ee516de87c484313e61fe069c7a..318c17162b8dc8c82e7db3e0896aae33a8ec8838 100644 (file)
@@ -269,12 +269,16 @@ int session_accept_fd(struct listener *l, int cfd, struct sockaddr_storage *addr
 
        /* error unrolling */
  out_free_sess:
+        /* prevent call to listener_release during session_free. It will be
+         * done below, for all errors. */
+       sess->listener = NULL;
        session_free(sess);
  out_free_conn:
        conn_stop_tracking(cli_conn);
        conn_xprt_close(cli_conn);
        conn_free(cli_conn);
  out_close:
+       listener_release(l);
        if (ret < 0 && l->bind_conf->xprt == xprt_get(XPRT_RAW) && p->mode == PR_MODE_HTTP) {
                /* critical error, no more memory, try to emit a 500 response */
                struct chunk *err_msg = &p->errmsg[HTTP_ERR_500];