From a522f801fb92e8435ce113127eefb16bf0dd2c2a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 23 Nov 2012 08:56:35 +0100 Subject: [PATCH] BUG/MEDIUM: checks: ensure we completely disable polling upon success 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 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/checks.c b/src/checks.c index 7f8311a2b..a2a7a35d3 100644 --- a/src/checks.c +++ b/src/checks.c @@ -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;