BUG/MINOR: listener: Don't decrease actconn twice when a new session is rejected

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.
This commit is contained in:
Christopher Faulet 2018-03-23 15:11:55 +01:00 committed by Willy Tarreau
parent 8adae7c15f
commit fe234281d6
2 changed files with 4 additions and 3 deletions

View 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;

View 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];