From ab0683580ba310130c673000f07b6965f472d4e9 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 14 Jul 2009 19:55:05 +0200 Subject: [PATCH] [BUG] stream_sock: don't stop reading when the poller reports an error As reported by Jean-Baptiste Quenot and Robbie Aelter, sometimes a backend server error is converted to a 502 error if the backend stops before reading all the request. The reason is that the remote system sends a TCP RST packet because there are still unread data pending in the socket buffer. This RST is translated as a socket error on the local system, and this error is reported by the poller. However, most of the time, it's a write error, but the system is still able to read the remaining pending data, such as in the trace below : send(7, "GET /aaa HTTP/1.0\r\nUser-Agent: Mo"..., 1123, MSG_DONTWAIT|MSG_NOSIGNAL) = 1123 epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLIN, {u32=7, u64=7}}) = 0 epoll_wait(3, {{EPOLLIN|EPOLLERR|EPOLLHUP, {u32=7, u64=7}}}, 8, 1000) = 1 gettimeofday({1247593958, 643572}, NULL) = 0 recv(7, "HTTP/1.0 400 Bad request\r\nCache-C"..., 7000, MSG_NOSIGNAL) = 187 setsockopt(6, SOL_TCP, TCP_NODELAY, [0], 4) = 0 setsockopt(6, SOL_TCP, TCP_CORK, [1], 4) = 0 send(6, "HTTP/1.0 400 Bad request\r\nCache-C"..., 187, MSG_DONTWAIT|MSG_NOSIGNAL) = 187 shutdown(6, 1 /* send */) = 0 The recv succeeded while epoll_wait() reported an error. Note: This case is very hard to reproduce and requires that the backend server is reached via the loopback in order to minimise latency and reduce the risk of sent data being ACKed. (cherry picked from commit 7154365cc60b124b543db4e98faedc75c0f3a2cb) --- src/stream_sock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stream_sock.c b/src/stream_sock.c index 8bfc55baa..d128defa6 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -54,7 +54,7 @@ int stream_sock_read(int fd) { retval = 1; /* stop immediately on errors */ - if (fdtab[fd].state == FD_STERROR || (fdtab[fd].ev & FD_POLL_ERR)) + if (fdtab[fd].state == FD_STERROR) goto out_error; /* stop here if we reached the end of data */ @@ -220,7 +220,7 @@ int stream_sock_write(int fd) { #endif retval = 1; - if (fdtab[fd].state == FD_STERROR || (fdtab[fd].ev & FD_POLL_ERR)) + if (fdtab[fd].state == FD_STERROR) goto out_error; while (1) { -- 2.47.3