]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: checks: avoid accumulating TIME_WAITs during checks
authorWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 08:18:20 +0000 (09:18 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 08:18:20 +0000 (09:18 +0100)
Some checks which do not induce a close from the server accumulate
local TIME_WAIT sockets because they're cleanly shut down. Typically
TCP probes cause this. This is very problematic when there are many
servers, when the checks are fast or when local source ports are rare.

So now we'll disable lingering on the socket instead of sending a
shutdown. Before doing this we try to drain any possibly pending data.
That way we avoid sending an RST when the server has closed first.

This change means that some servers will see more RSTs, but this is
needed to avoid local source port starvation.

src/checks.c

index d38823b0b84f1f523579c241c65946eaea4c514b..da4cd95b65bf8fcf58d1e52cebdfb9d981e1b438 100644 (file)
@@ -1157,11 +1157,18 @@ static void event_srv_chk_r(struct connection *conn)
        *s->check.bi->data = '\0';
        s->check.bi->i = 0;
 
-       /* Close the connection... */
+       /* Close the connection... We absolutely want to perform a hard close
+        * and reset the connection if some data are pending, otherwise we end
+        * up with many TIME_WAITs and eat all the source port range quickly.
+        * To avoid sending RSTs all the time, we first try to drain pending
+        * data.
+        */
        if (conn->xprt && conn->xprt->shutw)
                conn->xprt->shutw(conn, 0);
-       if (!(conn->flags & (CO_FL_WAIT_L4_CONN|CO_FL_SOCK_WR_SH)))
-               shutdown(conn->t.sock.fd, SHUT_RDWR);
+       if (!(conn->flags & CO_FL_WAIT_RD))
+               recv(conn->t.sock.fd, trash.str, trash.size, MSG_NOSIGNAL|MSG_DONTWAIT);
+       setsockopt(conn->t.sock.fd, SOL_SOCKET, SO_LINGER,
+                  (struct linger *) &nolinger, sizeof(struct linger));
        __conn_data_stop_both(conn);
        task_wakeup(t, TASK_WOKEN_IO);
        return;