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.
This commit is contained in:
Willy Tarreau 2012-11-23 08:56:35 +01:00
parent 6b0a850503
commit a522f801fb

View 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;