]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: connection: always disable polling upon error
authorWilly Tarreau <w@1wt.eu>
Sat, 24 Nov 2012 10:09:07 +0000 (11:09 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 24 Nov 2012 10:09:07 +0000 (11:09 +0100)
Commit 0ffde2cc in 1.5-dev13 tried to always disable polling on file
descriptors when errors were encountered. Unfortunately it did not
always succeed in doing so because it relied on detecting polling
changes to disable it. Let's use a dedicated conn_stop_polling()
function that is inconditionally called upon error instead.

This managed to stop a busy loop observed when a health check makes
use of the send-proxy protocol and fails before the connection can
be established.

include/proto/connection.h
src/connection.c

index 3bf337dcbd0c45121595ae1ba12b4d3421cd1fe6..35b6312bd55c5880153e560b572d213c607b3c21 100644 (file)
@@ -180,6 +180,17 @@ static inline void conn_cond_update_sock_polling(struct connection *c)
                conn_update_sock_polling(c);
 }
 
+/* Stop all polling on the fd. This might be used when an error is encountered
+ * for example.
+ */
+static inline void conn_stop_polling(struct connection *c)
+{
+       c->flags &= ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA |
+                     CO_FL_SOCK_RD_ENA | CO_FL_SOCK_WR_ENA |
+                     CO_FL_DATA_RD_ENA | CO_FL_DATA_WR_ENA);
+       fd_stop_both(c->t.sock.fd);
+}
+
 /* Automatically update polling on connection <c> depending on the DATA and
  * SOCK flags, and on whether a handshake is in progress or not. This may be
  * called at any moment when there is a doubt about the effectiveness of the
@@ -187,7 +198,9 @@ static inline void conn_cond_update_sock_polling(struct connection *c)
  */
 static inline void conn_cond_update_polling(struct connection *c)
 {
-       if (!(c->flags & CO_FL_POLL_SOCK) && conn_data_polling_changes(c))
+       if (unlikely(c->flags & CO_FL_ERROR))
+               conn_stop_polling(c);
+       else if (!(c->flags & CO_FL_POLL_SOCK) && conn_data_polling_changes(c))
                conn_update_data_polling(c);
        else if ((c->flags & CO_FL_POLL_SOCK) && conn_sock_polling_changes(c))
                conn_update_sock_polling(c);
index 8038a74648b14500a87cf329d626d4e2d41c78a9..9549dbae1bbe5fe37e2ffcd20c93a78f42ad20ea 100644 (file)
@@ -166,14 +166,6 @@ void conn_update_data_polling(struct connection *c)
 {
        unsigned int f = c->flags;
 
-       if (unlikely(f & CO_FL_ERROR)) {
-               c->flags &= ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA |
-                             CO_FL_SOCK_RD_ENA | CO_FL_SOCK_WR_ENA |
-                             CO_FL_DATA_RD_ENA | CO_FL_DATA_WR_ENA);
-               fd_stop_both(c->t.sock.fd);
-               return;
-       }
-
        /* update read status if needed */
        if (unlikely((f & (CO_FL_DATA_RD_ENA|CO_FL_WAIT_RD)) == (CO_FL_DATA_RD_ENA|CO_FL_WAIT_RD))) {
                fd_poll_recv(c->t.sock.fd);
@@ -214,14 +206,6 @@ void conn_update_sock_polling(struct connection *c)
 {
        unsigned int f = c->flags;
 
-       if (unlikely(f & CO_FL_ERROR)) {
-               c->flags &= ~(CO_FL_CURR_RD_ENA | CO_FL_CURR_WR_ENA |
-                             CO_FL_SOCK_RD_ENA | CO_FL_SOCK_WR_ENA |
-                             CO_FL_DATA_RD_ENA | CO_FL_DATA_WR_ENA);
-               fd_stop_both(c->t.sock.fd);
-               return;
-       }
-
        /* update read status if needed */
        if (unlikely((f & (CO_FL_SOCK_RD_ENA|CO_FL_WAIT_RD)) == (CO_FL_SOCK_RD_ENA|CO_FL_WAIT_RD))) {
                fd_poll_recv(c->t.sock.fd);