BUG/MEDIUM: sock: make sure to never miss early connection failures

As shown in issue #1251, it is possible for a connect() to report an
error directly via the poller without ever reporting send readiness,
but currentlt sock_conn_check() manages to ignore that situation,
leading to high CPU usage as poll() wakes up on these FDs.

The bug was apparently introduced in 1.5-dev22 with commit fd803bb4d
("MEDIUM: connection: add check for readiness in I/O handlers"), but
was likely only woken up by recent changes to conn_fd_handler() that
made use of wakeups instead of direct calls between 1.8 and 1.9,
voiding any chance to catch such errors in the early recv() callback.

The exact sequence that leads to this situation remains obscure though
because the poller does not report send readiness nor does it report an
error. Only HUP and IN are reported on the FD. It is also possible that
some recent kernel updates made this condition appear while it never
used to previously.

This needs to be backported to all stable branches, at least as far
as 2.0. Before 2.2 the code was in tcp_connect_probe() in proto_tcp.c.

(cherry picked from commit 5a9c637bf3f9daf595d5a5cd0e98961d6fdc4b1b)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 9547338fb4a4dda6aee428ee40aacf09ea2607b2)
[wt: code is in conn_fd_check() in 2.3]
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit 165560f1a47c6577917cf5677b78081c6bbc4cc0)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit aa6bc70f57d353bb89fb5af162caeff9e8ec34d6)
[cf: as specified, code is in tcp_connect_probe() in 2.2]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 23abea2..0689a7d 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -660,7 +660,7 @@
 	if (!(conn->flags & CO_FL_WAIT_L4_CONN))
 		return 1; /* strange we were called while ready */
 
-	if (!fd_send_ready(fd))
+	if (!fd_send_ready(fd) && !(fdtab[fd].state & (FD_POLL_ERR|FD_POLL_HUP)))
 		return 0;
 
 	/* we might be the first witness of FD_POLL_ERR. Note that FD_POLL_HUP