diff --git a/src/sock.c b/src/sock.c index 5340667bc1f4..3854aed66878 100644 --- a/src/sock.c +++ b/src/sock.c @@ -768,6 +768,30 @@ int sock_conn_check(struct connection *conn) goto done; if (!(fdtab[fd].state & (FD_POLL_ERR|FD_POLL_HUP))) goto wait; + + /* Removing HUP if there is no ERR reported. + * + * After a first connect() returning EINPROGRESS, it seems + * possible to have EPOLLHUP or EPOLLRDHUP reported by + * epoll_wait() and turned to an error while the following + * connect() will return a success. So the connection is + * validated but the error is saved and reported on the first + * subsequent read. + * + * We have no explanation for now. Why epoll report the + * connection is closed while the connect() it able to validate + * it ? no idea. But, it seems reasonnable in this case, and if + * no error was reported, to remove the the HUP flag. At worst, if + * the connection is really closed, this will be reported later. + * + * Only observed on Ubuntu kernel (5.4/5.15). See: + * - https://github.com/haproxy/haproxy/issues/1863 + * - https://www.spinics.net/lists/netdev/msg876470.html + */ + if (unlikely((fdtab[fd].state & (FD_POLL_HUP|FD_POLL_ERR)) == FD_POLL_HUP)) { + fdtab[fd].state &= ~FD_POLL_HUP; + } + /* error present, fall through common error check path */ }