From c7bd6705d4e2b757cb5e81169cffff164bdbc6df Mon Sep 17 00:00:00 2001 From: Tristan Rice Date: Thu, 17 Apr 2025 09:30:54 -0700 Subject: [PATCH] gloo/tcp/attr: hold on to bound socket to avoid port conflict issues (#429) Summary: Pull Request resolved: https://github.com/facebookincubator/gloo/pull/429 This is a minor refactor to attr in the TCP backend for Gloo so that we don't close the bound fd between allocating it in `lookupAddrForHostname` and binding it in `Listener`. Listener sets `SO_REUSEADDR` so it's fine for us to bind twice to the same address but we will only listen on it in `Listener`. Reviewed By: fduwjj Differential Revision: D73148977 --- gloo/transport/tcp/attr.h | 21 +++++++++++++++++++++ gloo/transport/tcp/device.cc | 5 ++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/gloo/transport/tcp/attr.h b/gloo/transport/tcp/attr.h index ca302c5d7..21b91f6d3 100644 --- a/gloo/transport/tcp/attr.h +++ b/gloo/transport/tcp/attr.h @@ -11,11 +11,30 @@ #include #include +#include +#include namespace gloo { namespace transport { namespace tcp { +// RAII for fds so they'll close when all references to them are freed. +class FDHolder { + public: + explicit FDHolder(int fd) : fd_(fd) {} + ~FDHolder() { + close(fd_); + } + + FDHolder(const FDHolder&) = delete; + FDHolder& operator=(const FDHolder&) = delete; + FDHolder(FDHolder&&) = delete; + FDHolder& operator=(FDHolder&&) = delete; + + private: + const int fd_; +}; + struct attr { attr() {} /* implicit */ attr(const char* ptr) : hostname(ptr) {} @@ -31,6 +50,8 @@ struct attr { int ai_protocol; struct sockaddr_storage ai_addr; int ai_addrlen; + + std::shared_ptr fd{nullptr}; }; } // namespace tcp diff --git a/gloo/transport/tcp/device.cc b/gloo/transport/tcp/device.cc index becd0af30..a381ba331 100644 --- a/gloo/transport/tcp/device.cc +++ b/gloo/transport/tcp/device.cc @@ -117,7 +117,10 @@ static void lookupAddrForHostname(struct attr& attr) { attr.ai_protocol = rp->ai_protocol; memcpy(&attr.ai_addr, rp->ai_addr, rp->ai_addrlen); attr.ai_addrlen = rp->ai_addrlen; - close(fd); + + // We explicitly don't close this FD here as we want to hold on to it until + // the listener binds the server socket to the port. + attr.fd = std::make_shared(fd); break; }