From 59b5da487368a976fa475848eaea5499ca007a19 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 4 Nov 2020 14:14:55 +0100 Subject: [PATCH] BUG/MEDIUM: listener: never suspend inherited sockets 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 | 6 ++++++ src/proto_udp.c | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/proto_tcp.c b/src/proto_tcp.c index d872ed318..e59aa961c 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -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; diff --git a/src/proto_udp.c b/src/proto_udp.c index bebcfb363..0724680a9 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -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;