diff --git a/include/proto/connection.h b/include/proto/connection.h index ddfb89e4e..0c07f8c33 100644 --- a/include/proto/connection.h +++ b/include/proto/connection.h @@ -114,6 +114,24 @@ void conn_update_data_polling(struct connection *c); */ int conn_local_send_proxy(struct connection *conn, unsigned int flag); +/* Refresh the connection's polling flags from its file descriptor status. + * This should be called at the beginning of a connection handler. + */ +static inline void conn_refresh_polling_flags(struct connection *conn) +{ + conn->flags &= ~(CO_FL_WAIT_ROOM | CO_FL_WAIT_RD | CO_FL_WAIT_DATA | CO_FL_WAIT_WR); + + if (conn->ctrl) { + unsigned int flags = conn->flags & ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA); + + if (fd_ev_is_set(conn->t.sock.fd, DIR_RD)) + flags |= CO_FL_CURR_RD_ENA; + if (fd_ev_is_set(conn->t.sock.fd, DIR_WR)) + flags |= CO_FL_CURR_WR_ENA; + conn->flags = flags; + } +} + /* inspects c->flags and returns non-zero if DATA ENA changes from the CURR ENA * or if the WAIT flags are set with their respective ENA flags. Additionally, * non-zero is also returned if an error was reported on the connection. This diff --git a/src/connection.c b/src/connection.c index 519a8f9ca..f86afde81 100644 --- a/src/connection.c +++ b/src/connection.c @@ -46,18 +46,8 @@ int conn_fd_handler(int fd) if (unlikely(!conn)) return 0; - /* before engaging there, we clear the new WAIT_* flags so that we can - * more easily detect an EAGAIN condition from anywhere. - */ - flags = conn->flags &= ~(CO_FL_WAIT_DATA|CO_FL_WAIT_ROOM|CO_FL_WAIT_RD|CO_FL_WAIT_WR); - flags &= ~CO_FL_ERROR; /* ensure to call the wake handler upon error */ - - /* adjust current polling status if it has been updated below us */ - if (fd_ev_is_set(conn->t.sock.fd, DIR_RD)) - conn->flags |= CO_FL_CURR_RD_ENA; - - if (fd_ev_is_set(conn->t.sock.fd, DIR_WR)) - conn->flags |= CO_FL_CURR_WR_ENA; + conn_refresh_polling_flags(conn); + flags = conn->flags & ~CO_FL_ERROR; /* ensure to call the wake handler upon error */ if (unlikely(conn->flags & CO_FL_ERROR)) goto leave; diff --git a/src/stream_interface.c b/src/stream_interface.c index 5f6d85d65..bba52e7e8 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -765,17 +765,20 @@ static void stream_int_chk_rcv_conn(struct stream_interface *si) if (unlikely(si->state > SI_ST_EST || (ib->flags & CF_SHUTR))) return; + conn_refresh_polling_flags(si->conn); + if ((ib->flags & CF_DONT_READ) || channel_full(ib)) { /* stop reading */ if (!(ib->flags & CF_DONT_READ)) /* full */ si->flags |= SI_FL_WAIT_ROOM; - conn_data_stop_recv(si->conn); + __conn_data_stop_recv(si->conn); } else { /* (re)start reading */ si->flags &= ~SI_FL_WAIT_ROOM; - conn_data_want_recv(si->conn); + __conn_data_want_recv(si->conn); } + conn_cond_update_data_polling(si->conn); } @@ -804,9 +807,8 @@ static void stream_int_chk_snd_conn(struct stream_interface *si) */ if (si->conn->ctrl) fd_want_send(si->conn->t.sock.fd); - si->conn->flags &= ~(CO_FL_WAIT_DATA|CO_FL_WAIT_ROOM|CO_FL_WAIT_RD|CO_FL_WAIT_WR); - if (fd_ev_is_set(si->conn->t.sock.fd, DIR_WR)) - si->conn->flags |= CO_FL_CURR_WR_ENA; + + conn_refresh_polling_flags(si->conn); if (si_conn_send_loop(si->conn) < 0) { /* Write error on the file descriptor */