]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: checks: ensure we completely disable polling upon success
authorWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 07:56:35 +0000 (08:56 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 08:03:59 +0000 (09:03 +0100)
When a check succeeds, it used to only disable receive events while
it should disable both directions. The problem is that if the send
event was reported too, it could re-enable the recv event. In theory
this is not a problem as the task is going to be woken up, but if
there are many tasks in the queue and this task is not processed
immediately, we could theorically face a storm of unprocessed events
(typically POLL_HUP).

So better stop both directions, prevent the send side from enabling
recv and have the process_chk() code enable both directions. This
will also help detecting closes before the check is sent.

Note that all this mess has been inherited from the old code that used
the fd as a flag to report if a check was running. We should have a
dedicated flag and perform the fd_delete() in wake_srv_chk() instead.

src/checks.c

index 7f8311a2b6f19f1c84710fbca9b74b45391ebdb0..a2a7a35d39a930c2a997a7d24b3870610324b600 100644 (file)
@@ -799,7 +799,6 @@ static void event_srv_chk_w(struct connection *conn)
                                t->expire = tick_add_ifset(now_ms, s->proxy->timeout.check);
                                task_queue(t);
                        }
-                       __conn_data_want_recv(conn);   /* prepare for reading reply */
                        goto out_nowake;
                }
                goto out_poll;
@@ -1163,7 +1162,7 @@ static void event_srv_chk_r(struct connection *conn)
                conn->xprt->shutw(conn, 0);
        if (!(conn->flags & (CO_FL_WAIT_L4_CONN|CO_FL_SOCK_WR_SH)))
                shutdown(conn->t.sock.fd, SHUT_RDWR);
-       __conn_data_stop_recv(conn);
+       __conn_data_stop_both(conn);
        task_wakeup(t, TASK_WOKEN_IO);
        return;
 
@@ -1324,6 +1323,7 @@ static struct task *process_chk(struct task *t)
                 * Additionnally, in the case of SN_ERR_RESOURCE, an emergency log will be emitted.
                 */
                ret = s->check.proto->connect(conn, 1);
+               __conn_data_want_recv(conn);   /* prepare for reading a possible reply */
                conn->flags |= CO_FL_WAKE_DATA;
                if (s->check.send_proxy)
                        conn->flags |= CO_FL_LOCAL_SPROXY;