From: Willy Tarreau Date: Mon, 25 Apr 2022 18:32:15 +0000 (+0200) Subject: MINOR: tree-wide: always consider EWOULDBLOCK in addition to EAGAIN X-Git-Tag: v2.6-dev8~76 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=acef5e27b0b89076308286208999cd31161cf741;p=thirdparty%2Fhaproxy.git MINOR: tree-wide: always consider EWOULDBLOCK in addition to EAGAIN Some older systems may routinely return EWOULDBLOCK for some syscalls while we tend to check only for EAGAIN nowadays. Modern systems define EWOULDBLOCK as EAGAIN so that solves it, but on a few older ones (AIX, VMS etc) both are different, and for portability we'd need to test for both or we never know if we risk to confuse some status codes with plain errors. There were few entries, the most annoying ones are the switch/case because they require to only add the entry when it differs, but the other ones are really trivial. --- diff --git a/src/check.c b/src/check.c index c39561a508..fdc82f526c 100644 --- a/src/check.c +++ b/src/check.c @@ -369,7 +369,7 @@ static const struct analyze_status analyze_statuses[HANA_STATUS_SIZE] = { /* 0: */ static inline int unclean_errno(int err) { - if (err == EAGAIN || err == EINPROGRESS || + if (err == EAGAIN || err == EWOULDBLOCK || err == EINPROGRESS || err == EISCONN || err == EALREADY) return 0; return err; diff --git a/src/connection.c b/src/connection.c index bc47ac886c..d37ad76d96 100644 --- a/src/connection.c +++ b/src/connection.c @@ -811,7 +811,7 @@ int conn_recv_proxy(struct connection *conn, int flag) if (ret < 0) { if (errno == EINTR) continue; - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { fd_cant_recv(conn->handle.fd); goto not_ready; } @@ -1287,7 +1287,7 @@ int conn_recv_netscaler_cip(struct connection *conn, int flag) if (ret < 0) { if (errno == EINTR) continue; - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { fd_cant_recv(conn->handle.fd); goto not_ready; } @@ -1581,7 +1581,7 @@ int conn_recv_socks4_proxy_response(struct connection *conn) if (errno == EINTR) { continue; } - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { fd_cant_recv(conn->handle.fd); goto not_ready; } diff --git a/src/dns.c b/src/dns.c index 9785c6e199..4a776a1eff 100644 --- a/src/dns.c +++ b/src/dns.c @@ -101,7 +101,7 @@ int dns_send_nameserver(struct dns_nameserver *ns, void *buf, size_t len) ret = send(fd, buf, len, 0); if (ret < 0) { - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { struct ist myist; myist = ist2(buf, len); @@ -155,7 +155,7 @@ ssize_t dns_recv_nameserver(struct dns_nameserver *ns, void *data, size_t size) return -1; if ((ret = recv(fd, data, size, 0)) < 0) { - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { fd_cant_recv(fd); return 0; } @@ -333,7 +333,7 @@ static void dns_resolve_send(struct dgram_conn *dgram) ret = send(fd, dns_msg_trash, len, 0); if (ret < 0) { - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { fd_cant_send(fd); goto out; } diff --git a/src/fd.c b/src/fd.c index c2dfcf1d6d..c983b8c9aa 100644 --- a/src/fd.c +++ b/src/fd.c @@ -666,7 +666,7 @@ void my_closefrom(int start) ret = poll(poll_events, fd - start, 0); if (ret >= 0) break; - } while (errno == EAGAIN || errno == EINTR || errno == ENOMEM); + } while (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR || errno == ENOMEM); if (ret) ret = fd - start; diff --git a/src/log.c b/src/log.c index 36d6d36cab..de9561d84a 100644 --- a/src/log.c +++ b/src/log.c @@ -1725,7 +1725,7 @@ static inline void __do_send_log(struct logsrv *logsrv, int nblogger, int level, if (sent < 0) { static char once; - if (errno == EAGAIN) + if (errno == EAGAIN || errno == EWOULDBLOCK) _HA_ATOMIC_INC(&dropped_logs); else if (!once) { once = 1; /* note: no need for atomic ops here */ @@ -3533,7 +3533,7 @@ void syslog_fd_handler(int fd) if (ret < 0) { if (errno == EINTR) continue; - if (errno == EAGAIN) + if (errno == EAGAIN || errno == EWOULDBLOCK) fd_cant_recv(fd); goto out; } diff --git a/src/mworker.c b/src/mworker.c index 2bc3b776f1..ccfcb5c6b7 100644 --- a/src/mworker.c +++ b/src/mworker.c @@ -384,7 +384,7 @@ void mworker_accept_wrapper(int fd) if (ret == -1) { if (errno == EINTR) continue; - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { fd_cant_recv(fd); return; } diff --git a/src/proto_quic.c b/src/proto_quic.c index b7d50df36d..eb3a316df3 100644 --- a/src/proto_quic.c +++ b/src/proto_quic.c @@ -467,9 +467,9 @@ int quic_connect_server(struct connection *conn, int flags) /* should normally not happen but if so, indicates that it's OK */ conn->flags &= ~CO_FL_WAIT_L4_CONN; } - else if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { + else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { char *msg; - if (errno == EAGAIN || errno == EADDRNOTAVAIL) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EADDRNOTAVAIL) { msg = "no free ports"; conn->err_code = CO_ER_FREE_PORTS; } diff --git a/src/proto_sockpair.c b/src/proto_sockpair.c index c63f02ae10..b244dd1b36 100644 --- a/src/proto_sockpair.c +++ b/src/proto_sockpair.c @@ -489,6 +489,9 @@ struct connection *sockpair_accept_conn(struct listener *l, int *status) } switch (errno) { +#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif case EAGAIN: ret = CO_AC_DONE; /* nothing more to accept */ if (fdtab[l->rx.fd].state & (FD_POLL_HUP|FD_POLL_ERR)) { diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 4aaac9d82f..738d2d113f 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -514,9 +514,9 @@ int tcp_connect_server(struct connection *conn, int flags) /* should normally not happen but if so, indicates that it's OK */ conn->flags &= ~CO_FL_WAIT_L4_CONN; } - else if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { + else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { char *msg; - if (errno == EAGAIN || errno == EADDRNOTAVAIL) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EADDRNOTAVAIL) { msg = "no free ports"; conn->err_code = CO_ER_FREE_PORTS; } diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 663369db43..2db4fa20b0 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -298,9 +298,9 @@ static int uxst_connect_server(struct connection *conn, int flags) else if (errno == EISCONN) { conn->flags &= ~CO_FL_WAIT_L4_CONN; } - else if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { + else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EADDRINUSE || errno == EADDRNOTAVAIL) { char *msg; - if (errno == EAGAIN || errno == EADDRNOTAVAIL) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EADDRNOTAVAIL) { msg = "can't connect to destination unix socket, check backlog size on the server"; conn->err_code = CO_ER_FREE_PORTS; } diff --git a/src/quic_sock.c b/src/quic_sock.c index 3baf3fd133..b6d2d18dca 100644 --- a/src/quic_sock.c +++ b/src/quic_sock.c @@ -289,7 +289,7 @@ void quic_sock_fd_iocb(int fd) do { ret = recvfrom(fd, dgram_buf, max_sz, 0, (struct sockaddr *)&saddr, &saddrlen); - if (ret < 0 && errno == EAGAIN) { + if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { fd_cant_recv(fd); goto out; } @@ -339,7 +339,7 @@ size_t qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t count, if (ret < try) break; } - else if (ret == 0 || errno == EAGAIN || errno == ENOTCONN || errno == EINPROGRESS) { + else if (ret == 0 || errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN || errno == EINPROGRESS) { /* TODO must be handle properly. It is justified for UDP ? */ ABORT_NOW(); } diff --git a/src/raw_sock.c b/src/raw_sock.c index cc72e6023f..b161f90f24 100644 --- a/src/raw_sock.c +++ b/src/raw_sock.c @@ -94,7 +94,7 @@ int raw_sock_to_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pipe, if (ret == 0) goto out_read0; - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* there are two reasons for EAGAIN : * - nothing in the socket buffer (standard) * - pipe is full @@ -191,7 +191,7 @@ int raw_sock_from_pipe(struct connection *conn, void *xprt_ctx, struct pipe *pip SPLICE_F_MOVE|SPLICE_F_NONBLOCK); if (ret <= 0) { - if (ret == 0 || errno == EAGAIN) { + if (ret == 0 || errno == EAGAIN || errno == EWOULDBLOCK) { fd_cant_send(conn->handle.fd); break; } @@ -301,7 +301,7 @@ static size_t raw_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu else if (ret == 0) { goto read0; } - else if (errno == EAGAIN || errno == ENOTCONN) { + else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN) { /* socket buffer exhausted */ fd_cant_recv(conn->handle.fd); break; @@ -395,7 +395,7 @@ static size_t raw_sock_from_buf(struct connection *conn, void *xprt_ctx, const s if (!count) fd_stop_send(conn->handle.fd); } - else if (ret == 0 || errno == EAGAIN || errno == ENOTCONN || errno == EINPROGRESS) { + else if (ret == 0 || errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN || errno == EINPROGRESS) { /* nothing written, we need to poll for write first */ fd_cant_send(conn->handle.fd); break; diff --git a/src/sock.c b/src/sock.c index 7ccdbd3baa..f4d8ba4d07 100644 --- a/src/sock.c +++ b/src/sock.c @@ -126,6 +126,9 @@ struct connection *sock_accept_conn(struct listener *l, int *status) sockaddr_free(&addr); switch (errno) { +#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif case EAGAIN: ret = CO_AC_DONE; /* nothing more to accept */ if (fdtab[l->rx.fd].state & (FD_POLL_HUP|FD_POLL_ERR)) { @@ -925,7 +928,7 @@ int sock_drain(struct connection *conn) goto shut; if (len < 0) { - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { /* connection not closed yet */ fd_cant_recv(fd); break; diff --git a/src/ssl_sock.c b/src/ssl_sock.c index fd2aff92a6..92121860ea 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -6503,7 +6503,7 @@ static size_t ssl_sock_to_buf(struct connection *conn, void *xprt_ctx, struct bu /* For SSL_ERROR_SYSCALL, make sure to clear the error * stack before shutting down the connection for * reading. */ - if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN)) + if (ret == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN || errno == EWOULDBLOCK)) goto clear_ssl_error; /* otherwise it's a real error */ goto out_error;