]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[OPTIM] stream_sock: don't shutdown(write) when the socket is in error
authorWilly Tarreau <w@1wt.eu>
Sat, 16 Jan 2010 09:03:45 +0000 (10:03 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 16 Jan 2010 09:03:45 +0000 (10:03 +0100)
We get a lot of those, especially with web crawlers :

recv(2, 0x810b610, 7000, 0)             = -1 ECONNRESET (Connection reset by peer)
shutdown(2, 1 /* send */)               = -1 ENOTCONN (Transport endpoint is not connected)
close(2)                                = 0

There's no need to perform the shutdown() here, the socket is already
in error so it is down.

src/stream_sock.c

index d84cd1a29fc89932e76655aa795d74b5d74be450..8937c2a56ddb18abda66feeb66df5363fe3c27d6 100644 (file)
@@ -823,7 +823,8 @@ int stream_sock_write(int fd)
  * This function performs a shutdown-write on a stream interface in a connected or
  * init state (it does nothing for other states). It either shuts the write side
  * or closes the file descriptor and marks itself as closed. The buffer flags are
- * updated to reflect the new state.
+ * updated to reflect the new state. It does also close everything is the SI was
+ * marked as being in error state.
  */
 void stream_sock_shutw(struct stream_interface *si)
 {
@@ -842,7 +843,10 @@ void stream_sock_shutw(struct stream_interface *si)
                 * However, if SI_FL_NOLINGER is explicitly set, we know there is
                 * no risk so we close both sides immediately.
                 */
-               if (si->flags & SI_FL_NOLINGER) {
+               if (si->flags & SI_FL_ERR) {
+                       /* quick close, the socket is already shut. Remove pending flags. */
+                       si->flags &= ~SI_FL_NOLINGER;
+               } else if (si->flags & SI_FL_NOLINGER) {
                        si->flags &= ~SI_FL_NOLINGER;
                        setsockopt(si->fd, SOL_SOCKET, SO_LINGER,
                                   (struct linger *) &nolinger, sizeof(struct linger));