]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: splice: disable it when the system returns EBADF
authorWilly Tarreau <w@1wt.eu>
Mon, 12 Nov 2012 11:00:09 +0000 (12:00 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 12 Nov 2012 11:02:20 +0000 (12:02 +0100)
At least on a heavily patched 2.6.35.9, we can see splice() fail
with EBADF :

  recv(6, "789.123456789.123456789.12345678"..., 1049, 0) = 1049
  send(5, "HTTP/1.1 200\r\nContent-length: 10"..., 8030, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE) = 8030
  gettimeofday({1352717854, 515601}, NULL) = 0
  epoll_wait(0x3, 0x40221008, 0x7, 0)     = 0
  gettimeofday({1352717854, 515793}, NULL) = 0
  pipe([7, 8])                            = 0
  splice(0x6, 0, 0x8, 0, 0xfe12c, 0x3)    = -1 EBADF (Bad file descriptor)
  close(6)                                = 0

This clearly is a kernel issue since all FDs are valid here, so let's
simply disable splice() on the connection when this happens so that
the session correctly recovers from that issue using recv().

src/raw_sock.c

index b7c9f2b7305fc3442ae88548e14695a052d00384..368b9f0830cba90dce7548b1bc765823cbf53104 100644 (file)
@@ -129,7 +129,7 @@ int raw_sock_to_pipe(struct connection *conn, struct pipe *pipe, unsigned int co
                                        __conn_data_poll_recv(conn); /* we know for sure that it's EAGAIN */
                                break;
                        }
-                       else if (errno == ENOSYS || errno == EINVAL) {
+                       else if (errno == ENOSYS || errno == EINVAL || errno == EBADF) {
                                /* splice not supported on this end, disable it.
                                 * We can safely return -1 since there is no
                                 * chance that any data has been piped yet.