commit f87ea7d2fdcfa3ccd5d605b3ce96642d28f20f6b Author: Willy Tarreau Date: Fri Aug 24 14:31:53 2018 +0200 BUG/MEDIUM: unix: provide a ->drain() function Right now conn_sock_drain() calls the protocol's ->drain() function if it exists, otherwise it simply tries to disable polling for receiving on the connection. This doesn't work well anymore since we've implemented the muxes in 1.8, and it has a side effect with keep-alive backend connections established over unix sockets. What happens is that if during the idle time after a request, a connection reports some data, si_idle_conn_null_cb() is called, which will call conn_sock_drain(). This one sees there's no drain() on unix sockets and will simply disable polling for data on the connection. But it doesn't do anything on the conn_stream. Thus while leaving the conn_fd_handler, the mux's polling is updated and recomputed based on the conn_stream's polling state, which is still enabled, and nothing changes, so we see the process use 100% CPU in this case because the FD remains active in the cache. There are several issues that need to be addressed here. The first and most important is that we cannot expect some protocols to simply stop reading data when asked to drain pending data. So this patch make the unix sockets rely on tcp_drain() since the functions are the same. This solution is appropriate for backporting, but a better one is desired for the long term. The second issue is that si_idle_conn_null_cb() shouldn't drain the connection but the conn_stream. At the moment we don't have any way to drain a conn_stream, though a flag on rcv_buf() will do it well. Until we support muxes on the server side it is not a problem so this part can be addressed later. This fix must be backported to 1.8. (cherry picked from commit fe5d2ac65fd58a8320e8dc725219c1bce5839592) Signed-off-by: Willy Tarreau diff --git a/src/proto_uxst.c b/src/proto_uxst.c index f2374be6..0b3a57b8 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -42,6 +42,7 @@ #include #include #include +#include #include static int uxst_bind_listener(struct listener *listener, char *errmsg, int errlen); @@ -71,6 +72,7 @@ static struct protocol proto_unix = { .disable_all = disable_all_listeners, .get_src = uxst_get_src, .get_dst = uxst_get_dst, + .drain = tcp_drain, .pause = uxst_pause_listener, .add = uxst_add_listener, .listeners = LIST_HEAD_INIT(proto_unix.listeners),