|
commit f87ea7d2fdcfa3ccd5d605b3ce96642d28f20f6b
|
|
Author: Willy Tarreau <w@1wt.eu>
|
|
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 <w@1wt.eu>
|
|
|
|
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 <proto/listener.h>
|
|
#include <proto/log.h>
|
|
#include <proto/protocol.h>
|
|
+#include <proto/proto_tcp.h>
|
|
#include <proto/task.h>
|
|
|
|
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),
|