From b7f1cfc8463382fdb230b537bf297f1ce4854d49 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Wed, 11 Jun 2014 00:15:51 +0200 Subject: [PATCH] BUG/MEDIUM: Fix unhandled connections problem with systemd daemon mode and SO_REUSEPORT. Using the systemd daemon mode the parent doesn't exits but waits for his childs without closing its listening sockets. As linux 3.9 introduced a SO_REUSEPORT option (always enabled in haproxy if available) this will give unhandled connections problems after an haproxy reload with open connections. The problem is that when on reload a new parent is started (-Ds $oldchildspids), in haproxy.c main there's a call to start_proxies that, without SO_REUSEPORT, should fail (as the old processes are already listening) and so a SIGTOU is sent to old processes. On this signal the old childs will call (in pause_listener) a shutdown() on the listening fd. From my tests (if I understand it correctly) this affects the in kernel file (so the listen is really disabled for all the processes, also the parent). Instead, with SO_REUSEPORT, the call to start_proxies doesn't fail and so SIGTOU is never sent. Only SIGUSR1 is sent and the listen isn't disabled for the parent but only the childs will stop listening (with a call to close()) So, with SO_REUSEPORT, the old childs will close their listening sockets but will wait for the current connections to finish or timeout, and, as their parent has its listening socket open, the kernel will schedule some connections on it. These connections will never be accepted by the parent as it's in the waitpid loop. This fix will close all the listeners on the parent before entering the waitpid loop. Signed-off-by: Simone Gotti --- src/haproxy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/haproxy.c b/src/haproxy.c index d8d8c61a3..6bfab069c 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1604,6 +1604,7 @@ int main(int argc, char **argv) if (proc == global.nbproc) { if (global.mode & MODE_SYSTEMD) { + protocol_unbind_all(); for (proc = 0; proc < global.nbproc; proc++) while (waitpid(children[proc], NULL, 0) == -1 && errno == EINTR); }