diff --git a/src/connection.c b/src/connection.c index 03a9bb08b..4bb497ef2 100644 --- a/src/connection.c +++ b/src/connection.c @@ -52,6 +52,13 @@ int conn_fd_handler(int fd) 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; + if (unlikely(conn->flags & CO_FL_ERROR)) goto leave; diff --git a/src/stream_interface.c b/src/stream_interface.c index dc1485883..9679e1690 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -799,15 +799,23 @@ static void stream_int_chk_snd_conn(struct stream_interface *si) (fdtab[si->conn->t.sock.fd].ev & FD_POLL_OUT))) /* we'll be called anyway */ return; - if (!(si->conn->flags & CO_FL_HANDSHAKE) && si_conn_send_loop(si->conn) < 0) { - /* Write error on the file descriptor. We mark the FD as STERROR so - * that we don't use it anymore and we notify the task. + if (!(si->conn->flags & (CO_FL_HANDSHAKE|CO_FL_WAIT_L4_CONN|CO_FL_WAIT_L6_CONN))) { + /* Before calling the data-level operations, we have to prepare + * the polling flags to ensure we properly detect changes. */ - fdtab[si->conn->t.sock.fd].ev &= ~FD_POLL_STICKY; - __conn_data_stop_both(si->conn); - si->flags |= SI_FL_ERR; - si->conn->flags |= CO_FL_ERROR; - goto out_wakeup; + 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); + si->conn->flags |= CO_FL_CURR_WR_ENA; + + if (si_conn_send_loop(si->conn) < 0) { + /* Write error on the file descriptor */ + fd_stop_both(si->conn->t.sock.fd); + __conn_data_stop_both(si->conn); + si->flags |= SI_FL_ERR; + si->conn->flags |= CO_FL_ERROR; + goto out_wakeup; + } } /* OK, so now we know that some data might have been sent, and that we may @@ -819,6 +827,7 @@ static void stream_int_chk_snd_conn(struct stream_interface *si) * ->o limit was reached. Maybe we just wrote the last * chunk and need to close. */ + __conn_data_stop_send(si->conn); if (((ob->flags & (CF_SHUTW|CF_AUTO_CLOSE|CF_SHUTW_NOW)) == (CF_AUTO_CLOSE|CF_SHUTW_NOW)) && (si->state == SI_ST_EST)) {