]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: listener: never suspend inherited sockets
authorWilly Tarreau <w@1wt.eu>
Wed, 4 Nov 2020 13:14:55 +0000 (14:14 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 4 Nov 2020 13:22:42 +0000 (14:22 +0100)
It is not acceptable to suspend an inherited socket because we'd kill
its listening state, making it possibly unrecoverable for future
processes. The situation which can trigger this is when there is an
abns socket in a config and an inherited FD on another listener. Upon
soft reload, the abns fails to bind, a SIGTTOU is sent to the old
process which suspends everything, including the inherited FD, then
the new process can bind and tell the old one to quit. Except that the
new FD was not set back to the listen state, which is detected by
listener_accept() which can pause it. It's only upon second reload
that the FD works again.

The solution is to refrain from suspending such FDs since we don't own
them. And the next process will get them right anyway from its config.
For now only TCP and UDP face this issue so it's better to address this
on a protocol basis

No backport is needed, this is related to the new listeners in 2.3.

src/proto_tcp.c
src/proto_udp.c

index d872ed318215d10d0b5ca19a3737f3804235c360..e59aa961cbc9cb8dea385298ff38287830d63bdc 100644 (file)
@@ -774,6 +774,12 @@ static int tcp_suspend_receiver(struct receiver *rx)
        const struct sockaddr sa = { .sa_family = AF_UNSPEC };
        int ret;
 
+       /* we never do that with a shared FD otherwise we'd break it in the
+        * parent process and any possible subsequent worker inheriting it.
+        */
+       if (rx->flags & RX_F_INHERITED)
+               return -1;
+
        if (connect(rx->fd, &sa, sizeof(sa)) < 0)
                goto check_already_done;
 
index bebcfb36373d2de85944a7218859b35c5d36de67..0724680a9a654997fba6ec25f8515721fa61b20d 100644 (file)
@@ -206,6 +206,12 @@ static int udp_suspend_receiver(struct receiver *rx)
        if (rx->fd < 0)
                return 0;
 
+       /* we never do that with a shared FD otherwise we'd break it in the
+        * parent process and any possible subsequent worker inheriting it.
+        */
+       if (rx->flags & RX_F_INHERITED)
+               return -1;
+
        if (getsockname(rx->fd, (struct sockaddr *)&ss, &len) < 0)
                return -1;