]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: raw_sock: improve connection error reporting
authorWilly Tarreau <w@1wt.eu>
Thu, 4 Oct 2012 18:38:49 +0000 (20:38 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 4 Oct 2012 20:26:09 +0000 (22:26 +0200)
When a connection setup is pending and we receive an error without a
POLL_IN flag, we're certain there will be nothing to read from it and
we can safely report an error without attempting a recv() call. This
will be significantly better for health checks which will avoid a useless
recv() on all failed checks.

src/raw_sock.c

index c417d5a7d3f066d26a1ee340f84a2e5c8d7b20b1..1330fadd70d45c0f6ca11e2b4593d90bbf60e2f8 100644 (file)
@@ -70,8 +70,17 @@ int raw_sock_to_pipe(struct connection *conn, struct pipe *pipe, unsigned int co
         * Since older splice() implementations were buggy and returned
         * EAGAIN on end of read, let's bypass the call to splice() now.
         */
-       if ((fdtab[conn->t.sock.fd].ev & (FD_POLL_IN|FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP)
-               goto out_read0;
+       if (unlikely(!(fdtab[conn->t.sock.fd].ev & FD_POLL_IN))) {
+               /* stop here if we reached the end of data */
+               if ((fdtab[conn->t.sock.fd].ev & (FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP)
+                       goto out_read0;
+
+               /* report error on POLL_ERR before connection establishment */
+               if ((fdtab[conn->t.sock.fd].ev & FD_POLL_ERR) && (conn->flags & CO_FL_WAIT_L4_CONN)) {
+                       conn->flags |= CO_FL_ERROR;
+                       return retval;
+               }
+       }
 
        while (count) {
                if (count > MAX_SPLICE_AT_ONCE)
@@ -201,9 +210,17 @@ static int raw_sock_to_buf(struct connection *conn, struct buffer *buf, int coun
        int ret, done = 0;
        int try = count;
 
-       /* stop here if we reached the end of data */
-       if ((fdtab[conn->t.sock.fd].ev & (FD_POLL_IN|FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP)
-               goto read0;
+       if (unlikely(!(fdtab[conn->t.sock.fd].ev & FD_POLL_IN))) {
+               /* stop here if we reached the end of data */
+               if ((fdtab[conn->t.sock.fd].ev & (FD_POLL_ERR|FD_POLL_HUP)) == FD_POLL_HUP)
+                       goto read0;
+
+               /* report error on POLL_ERR before connection establishment */
+               if ((fdtab[conn->t.sock.fd].ev & FD_POLL_ERR) && (conn->flags & CO_FL_WAIT_L4_CONN)) {
+                       conn->flags |= CO_FL_ERROR;
+                       return done;
+               }
+       }
 
        /* compute the maximum block size we can read at once. */
        if (buffer_empty(buf)) {