diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 2dbfb64f8..0c86d6eb6 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -760,22 +760,24 @@ static void tcp_disable_listener(struct listener *l) } /* Suspend a receiver. Returns < 0 in case of failure, 0 if the receiver - * was totally stopped, or > 0 if correctly suspended. + * was totally stopped, or > 0 if correctly suspended. Note that inherited FDs + * are neither suspended nor resumed, we only enable/disable polling on them. */ 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 + /* We never disconnect a shared FD otherwise we'd break it in the * parent process and any possible subsequent worker inheriting it. + * Thus we just stop receiving from it. */ if (rx->flags & RX_F_INHERITED) - return -1; + goto done; if (connect(rx->fd, &sa, sizeof(sa)) < 0) goto check_already_done; - + done: fd_stop_recv(rx->fd); return 1; @@ -796,7 +798,8 @@ static int tcp_suspend_receiver(struct receiver *rx) } /* Resume a receiver. Returns < 0 in case of failure, 0 if the receiver - * was totally stopped, or > 0 if correctly suspended. + * was totally stopped, or > 0 if correctly resumed. Note that inherited FDs + * are neither suspended nor resumed, we only enable/disable polling on them. */ static int tcp_resume_receiver(struct receiver *rx) { @@ -805,7 +808,7 @@ static int tcp_resume_receiver(struct receiver *rx) if (rx->fd < 0) return 0; - if (listen(rx->fd, listener_backlog(l)) == 0) { + if ((rx->flags & RX_F_INHERITED) || listen(rx->fd, listener_backlog(l)) == 0) { fd_want_recv(l->rx.fd); return 1; } diff --git a/src/proto_udp.c b/src/proto_udp.c index 542d287c0..1fd92c7ce 100644 --- a/src/proto_udp.c +++ b/src/proto_udp.c @@ -176,7 +176,9 @@ static void udp_disable_listener(struct listener *l) * suspend the receiver, we want it to stop receiving traffic, which means that * the socket must be unhashed from the kernel's socket table. The simple way * to do this is to connect to any address that is reachable and will not be - * used by regular traffic, and a great one is reconnecting to self. + * used by regular traffic, and a great one is reconnecting to self. Note that + * inherited FDs are neither suspended nor resumed, we only enable/disable + * polling on them. */ int udp_suspend_receiver(struct receiver *rx) { @@ -190,14 +192,14 @@ int udp_suspend_receiver(struct receiver *rx) * parent process and any possible subsequent worker inheriting it. */ if (rx->flags & RX_F_INHERITED) - return -1; + goto done; if (getsockname(rx->fd, (struct sockaddr *)&ss, &len) < 0) return -1; if (connect(rx->fd, (struct sockaddr *)&ss, len) < 0) return -1; - + done: /* not necessary but may make debugging clearer */ fd_stop_recv(rx->fd); return 1; @@ -207,7 +209,8 @@ int udp_suspend_receiver(struct receiver *rx) * was totally stopped, or > 0 if correctly suspended. * The principle is to reverse the change above, we'll break the connection by * connecting to AF_UNSPEC. The association breaks and the socket starts to - * receive from everywhere again. + * receive from everywhere again. Note that inherited FDs are neither suspended + * nor resumed, we only enable/disable polling on them. */ int udp_resume_receiver(struct receiver *rx) { @@ -216,7 +219,7 @@ int udp_resume_receiver(struct receiver *rx) if (rx->fd < 0) return 0; - if (connect(rx->fd, &sa, sizeof(sa)) < 0) + if (!(rx->flags & RX_F_INHERITED) && connect(rx->fd, &sa, sizeof(sa)) < 0) return -1; fd_want_recv(rx->fd);