]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] prevent the system from sending an RST when closing health-checks
authorKrzysztof Oledzki <ole@ans.pl>
Thu, 11 Oct 2007 16:41:08 +0000 (18:41 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 15 Oct 2007 07:32:58 +0000 (09:32 +0200)
On Sat, 22 Sep 2007, Willy Tarreau wrote:
> On Sun, Sep 23, 2007 at 03:23:38AM +0200, Krzysztof Oledzki wrote:
> > I noticed that with httpchk, haproxy generates TCP RST at end of a check.
> > IMHO, it would be more polite to send FIN to a server, especially that
> > each TCP RST found by a tcpdump makes me concerned that something is
> > wrong, as it is hard to distinguish between a RST from a httpchk and from
> > a normal request, forwarded for a client.
>
> I have also noticed it very recently. In fact, it's never the
> application (here haproxy) which decides to send an RST, it's the
> system. It does so because the server returns data on a terminated
> socket. I guess it's because the health-check code does not read much
> of the response. In fact, we just need to read enough to process common
> responses. If people are dumb enough to check with something like "GET
> /image.iso", they should expect to get an RST after a few kbytes
> instead of reading the whole file!

Right, that was easy. Attached patch changed what you described. Now
haproxy finishes http checks with FIN.

src/checks.c

index 2c581ef1c8bf147171eb97532dbb23885f523edc..62f0c2c711db93cd6fc12069a5de7fc019a8f77d 100644 (file)
@@ -210,7 +210,6 @@ static int event_srv_chk_w(int fd)
 static int event_srv_chk_r(int fd)
 {
        __label__ out_wakeup;
-       char reply[64];
        int len, result;
        struct task *t = fdtab[fd].owner;
        struct server *s = t->context;
@@ -230,13 +229,13 @@ static int event_srv_chk_r(int fd)
        }
 
 #ifndef MSG_NOSIGNAL
-       len = recv(fd, reply, sizeof(reply), 0);
+       len = recv(fd, trash, sizeof(trash), 0);
 #else
        /* Warning! Linux returns EAGAIN on SO_ERROR if data are still available
         * but the connection was closed on the remote end. Fortunately, recv still
         * works correctly and we don't need to do the getsockopt() on linux.
         */
-       len = recv(fd, reply, sizeof(reply), MSG_NOSIGNAL);
+       len = recv(fd, trash, sizeof(trash), MSG_NOSIGNAL);
 #endif
        if (unlikely(len < 0 && errno == EAGAIN)) {
                /* we want some polling to happen first */
@@ -245,17 +244,17 @@ static int event_srv_chk_r(int fd)
        }
 
        if ((s->proxy->options & PR_O_HTTP_CHK) && (len >= sizeof("HTTP/1.0 000")) &&
-            (memcmp(reply, "HTTP/1.", 7) == 0) && (reply[9] == '2' || reply[9] == '3')) {
+            (memcmp(trash, "HTTP/1.", 7) == 0) && (trash[9] == '2' || trash[9] == '3')) {
                /* HTTP/1.X 2xx or 3xx */
                result = 1;
        }
        else if ((s->proxy->options & PR_O_SSL3_CHK) && (len >= 5) &&
-                (reply[0] == 0x15 || reply[0] == 0x16)) {
+                (trash[0] == 0x15 || trash[0] == 0x16)) {
                /* SSLv3 alert or handshake */
                result = 1;
        }
        else if ((s->proxy->options & PR_O_SMTP_CHK) && (len >= 3) &&
-                  (reply[0] == '2')) /* 2xx (should be 250) */ {
+                  (trash[0] == '2')) /* 2xx (should be 250) */ {
                result = 1;
        }