<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-ports.
</pre>
<p><a href="https://github.com/macports/macports-ports/commit/671ce78ffd0a91921cf353cd2110e50cf04082bb">https://github.com/macports/macports-ports/commit/671ce78ffd0a91921cf353cd2110e50cf04082bb</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 671ce78ffd0a91921cf353cd2110e50cf04082bb
</span>Author: barracuda156 <vital.had@gmail.com>
AuthorDate: Wed May 17 20:40:50 2023 +0800
<span style='display:block; white-space:pre;color:#404040;'> folly: revert breaking changes for <= 10.15
</span>---
devel/folly/Portfile | 14 +
...te-methods-to-dcheck-ToSend-Received-OrEm.patch | 35 ++
...popNextReceivedFds-using-ReadAncillaryDat.patch | 282 +++++++++++
...ge-cloneToSendFrom-to-DFATAL-instead-of-C.patch | 37 ++
...vert-Add-const-to-help-with-thread-safety.patch | 30 ++
devel/folly/files/0005-Revert-Unit-tests.patch | 330 +++++++++++++
...eChainWithFds-using-SendMsgParamsCallback.patch | 539 +++++++++++++++++++++
7 files changed, 1267 insertions(+)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/Portfile b/devel/folly/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index c08ad006d29..f612aca612e 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/devel/folly/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -71,6 +71,20 @@ cmake.generator Ninja
</span>
patchfiles-append patch-older-systems.diff
<span style='display:block; white-space:pre;background:#e0ffe0;'>+# This is a temporary revert of breaking commits until this can be properly fixed.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+# See: https://github.com/macports/macports-ports/commit/03289e4611ed4b387ce916214c7c6a6a105e25e0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+platform darwin {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {${os.major} < 20} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ patchfiles-append \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 0001-Revert-Update-methods-to-dcheck-ToSend-Received-OrEm.patch \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 0002-Revert-Add-popNextReceivedFds-using-ReadAncillaryDat.patch \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 0003-Revert-Change-cloneToSendFrom-to-DFATAL-instead-of-C.patch \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 0004-Revert-Add-const-to-help-with-thread-safety.patch \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 0005-Revert-Unit-tests.patch \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 0006-Revert-writeChainWithFds-using-SendMsgParamsCallback.patch
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> configure.args-append -DBUILD_SHARED_LIBS=ON \
-DFOLLY_USE_JEMALLOC=0
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/files/0001-Revert-Update-methods-to-dcheck-ToSend-Received-OrEm.patch b/devel/folly/files/0001-Revert-Update-methods-to-dcheck-ToSend-Received-OrEm.patch
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..70de6f1265c
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/files/0001-Revert-Update-methods-to-dcheck-ToSend-Received-OrEm.patch
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,35 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From 746e0e38b8853f55c4b4310afb517faa1899b623 Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: barracuda156 <vital.had@gmail.com>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Wed, 17 May 2023 14:37:00 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH 1/6] Revert "Update methods to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ `dcheck{ToSend,Received}OrEmpty()`"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit ace41c041175402779b1c05981b5dd7a48a4ee46.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/SocketFds.h | 8 ++++----
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 1 file changed, 4 insertions(+), 4 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/SocketFds.h folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 965bdb5ac..620a5dd0a 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -83,12 +83,12 @@ class SocketFds final {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ DCHECK(!ptr_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return *this;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds& dcheckReceivedOrEmpty() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK(!ptr_ || std::holds_alternative<Received>(*ptr_));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SocketFds& dcheckReceived() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ DCHECK(std::holds_alternative<Received>(*ptr_));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return *this;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds& dcheckToSendOrEmpty() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK(!ptr_ || std::holds_alternative<ToSend>(*ptr_));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SocketFds& dcheckToSend() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ DCHECK(std::holds_alternative<ToSend>(*ptr_));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return *this;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+2.40.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/files/0002-Revert-Add-popNextReceivedFds-using-ReadAncillaryDat.patch b/devel/folly/files/0002-Revert-Add-popNextReceivedFds-using-ReadAncillaryDat.patch
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..cd900c94603
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/files/0002-Revert-Add-popNextReceivedFds-using-ReadAncillaryDat.patch
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,282 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From d7a0a0e96bcbdfad5819fd12eff9307f40ddd298 Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: barracuda156 <vital.had@gmail.com>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Wed, 17 May 2023 14:38:31 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH 2/6] Revert "Add `popNextReceivedFds` using
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ `ReadAncillaryDataCallback`"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 185e3b2b18fca08f4ce7f58bd2cc50e53c1a3a3d.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/AsyncSocket.cpp | 7 +-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/AsyncFdSocket.cpp | 114 +-----------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/AsyncFdSocket.h | 54 +----------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 3 files changed, 6 insertions(+), 169 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/AsyncSocket.cpp folly/io/async/AsyncSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 696b18729..8339b586b 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/AsyncSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/AsyncSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -2513,22 +2513,17 @@ AsyncSocket::ReadResult AsyncSocket::performReadMsg(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ bytes = netops_->recv(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fd_, msg.msg_iov[0].iov_base, msg.msg_iov[0].iov_len, MSG_DONTWAIT);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- int recvFlags = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (readAncillaryDataCallback_) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ auto buf = readAncillaryDataCallback_->getAncillaryDataCtrlBuffer();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ msg.msg_control = buf.data();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ msg.msg_controllen = buf.size();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if defined(__linux__)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // On BSD / MacOS, `AsyncFdSocket` has to do 2 extra `fcntl`s per FD.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- recvFlags |= MSG_CMSG_CLOEXEC;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ msg.msg_control = nullptr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ msg.msg_controllen = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // `msg.msg_iov*` were set by the caller, we're ready.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- bytes = netops::recvmsg(fd_, &msg, recvFlags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ bytes = netops::recvmsg(fd_, &msg, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // KEY INVARIANT: If `bytes > 0`, we must proceed to `ancillaryData` --
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // no error branches must interrupt this flow. The reason is that
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/AsyncFdSocket.cpp folly/io/async/fdsock/AsyncFdSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 24ce50111..d8cadc038 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/AsyncFdSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/fdsock/AsyncFdSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -22,8 +22,7 @@ AsyncFdSocket::AsyncFdSocket(EventBase* evb)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ : AsyncSocket(evb)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendMsgCob_(evb),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- readAncillaryDataCob_(this) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ sendMsgCob_(evb) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ setUpCallbacks();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -44,8 +43,7 @@ AsyncFdSocket::AsyncFdSocket(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ : AsyncSocket(evb, fd, /* zeroCopyBufId */ 0, peerAddress)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendMsgCob_(evb),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- readAncillaryDataCob_(this) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ sendMsgCob_(evb) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ setUpCallbacks();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -99,7 +97,6 @@ void AsyncFdSocket::writeChainWithFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ void AsyncFdSocket::setUpCallbacks() noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ AsyncSocket::setSendMsgParamCB(&sendMsgCob_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocket::setReadAncillaryDataCB(&readAncillaryDataCob_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ void AsyncFdSocket::releaseIOBuf(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -202,113 +199,6 @@ void AsyncFdSocket::FdSendMsgParamsCallback::destroyFdsForWriteTag(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ << nh.mapped().size() << " FDs for tag " << writeTag;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-namespace {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// Logs and returns `false` on error.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-bool receiveFdsFromCMSG(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const struct ::cmsghdr& cmsg, std::vector<folly::File>* fds) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (cmsg.cmsg_len < CMSG_LEN(sizeof(int))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(ERROR) << "Got truncated SCM_RIGHTS message: length=" << cmsg.cmsg_len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const size_t dataLength = cmsg.cmsg_len - CMSG_LEN(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const size_t numFDs = dataLength / sizeof(int);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if ((dataLength % sizeof(int)) != 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(ERROR) << "Non-integer number of file descriptors: size=" << dataLength;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const auto* data = reinterpret_cast<const int*>(CMSG_DATA(&cmsg));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (size_t n = 0; n < numFDs; ++n) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto fd = data[n];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// On Linux, `AsyncSocket` sets `MSG_CMSG_CLOEXEC` for us.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if !defined(__linux__)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- int flags = ::fcntl(fd, F_GETFD);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // On error, "fail open" by leaving the FD unmodified.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (UNLIKELY(flags == -1)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PLOG(ERROR) << "FdReadAncillaryDataCallback F_GETFD";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- } else if (UNLIKELY(-1 == ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PLOG(ERROR) << "FdReadAncillaryDataCallback F_SETFD";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif // !Linux
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- fds->emplace_back(fd, /*owns_fd*/ true);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// Logs and returns `false` on error.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-bool receiveFds(struct ::msghdr& msg, std::vector<folly::File>* fds) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- struct ::cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- while (cmsg) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (cmsg->cmsg_level != SOL_SOCKET) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(ERROR) << "Unexpected cmsg_level=" << cmsg->cmsg_level;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- } else if (cmsg->cmsg_type != SCM_RIGHTS) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(ERROR) << "Unexpected cmsg_type=" << cmsg->cmsg_type;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!receiveFdsFromCMSG(*cmsg, fds)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- cmsg = CMSG_NXTHDR(&msg, cmsg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-} // namespace
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void AsyncFdSocket::enqueueFdsFromAncillaryData(struct ::msghdr& msg) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- eventBase_->dcheckIsInEventBaseThread();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (msg.msg_flags & MSG_CTRUNC) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException ex(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException::INTERNAL_ERROR,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- "Got MSG_CTRUNC because the `AsyncFdSocket` buffer was too small");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocket::failRead(__func__, ex);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::vector<folly::File> fds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!receiveFds(msg, &fds)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException ex(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException::INTERNAL_ERROR,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- "Failed to read FDs from msghdr.msg_control");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocket::failRead(__func__, ex);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Don't waste queue space with empty FD lists since we match FDs only to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // requests that claim to include FDs.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (fds.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- VLOG(4) << "this=" << this << ", enqueueFdsFromAncillaryData() got "
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- << fds.size() << " FDs, prev queue size " << fdsQueue_.size();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- fdsQueue_.emplace(std::move(fds));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #endif // !Windows
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-std::optional<SocketFds::Received> AsyncFdSocket::popNextReceivedFds() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return std::nullopt;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- eventBase_->dcheckIsInEventBaseThread();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK_EQ(&readAncillaryDataCob_, getReadAncillaryDataCallback());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (fdsQueue_.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return std::nullopt;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto fds = std::move(fdsQueue_.front());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- fdsQueue_.pop();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return fds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif // !Windows
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ } // namespace folly
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/AsyncFdSocket.h folly/io/async/fdsock/AsyncFdSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 65e43dcff..d72d086ac 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/AsyncFdSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/fdsock/AsyncFdSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -16,8 +16,6 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #pragma once
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <optional>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <folly/io/async/AsyncSocket.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <folly/io/async/fdsock/SocketFds.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -27,9 +25,9 @@ namespace folly {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Intended for use with Unix sockets. Unlike regular `AsyncSocket`:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * - Can send FDs via `writeChainWithFds` using socket ancillary data (see
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * `man cmsg`).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - Whenever handling regular reads, concurrently attempts to receive FDs
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * included in incoming ancillary data. Groups of received FDs are
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * enqueued to be retrieved via `popNextReceivedFds`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * - Always attempts to receive FDs included in incoming ancillary data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * Groups of received FDs are enqueued to be retrieved via
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ * `popNextReceivedFds`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * - The "read ancillary data" and "sendmsg params" callbacks are built-in
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * are NOT customizable.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -95,24 +93,9 @@ class AsyncFdSocket : public AsyncSocket {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ SocketFds::ToSend,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ WriteFlags flags = WriteFlags::NONE);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * This socket will look for file descriptors in the ancillary data (`man
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * cmsg`) of each incoming read.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - FDs are kept in an internal queue, to be retrieved via this call.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - FDs are marked with FD_CLOEXEC upon receipt, although on non-Linux
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * platforms there is a short race window before this happens.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - Empty lists of FDs (0 FDs with this message) are not stored in the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * queue.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - Returns `std::nullopt` if the queue is empty.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::optional<SocketFds::Received> popNextReceivedFds();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ void setSendMsgParamCB(SendMsgParamsCallback*) override {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ LOG(DFATAL) << "AsyncFdSocket::setSendMsgParamCB is forbidden";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void setReadAncillaryDataCB(ReadAncillaryDataCallback*) override {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(DFATAL) << "AsyncFdSocket::setReadAncillaryDataCB is forbidden";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // This uses no ancillary data callbacks on Windows, they wouldn't compile.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -166,40 +149,9 @@ class AsyncFdSocket : public AsyncSocket {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ WriteTagToFds writeTagToFds_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- class FdReadAncillaryDataCallback : public ReadAncillaryDataCallback {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- explicit FdReadAncillaryDataCallback(AsyncFdSocket* socket)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : socket_(socket) {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void ancillaryData(struct ::msghdr& msg) noexcept override {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- socket_->enqueueFdsFromAncillaryData(msg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- folly::MutableByteRange getAncillaryDataCtrlBuffer() noexcept override {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Not checking thread because `ancillaryData()` will follow.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return folly::MutableByteRange(ancillaryDataCtrlBuffer_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Max number of fds in a single `sendmsg` / `recvmsg` message
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Defined as SCM_MAX_FD in linux/include/net/scm.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- static constexpr size_t kMaxFdsPerSocketMsg{253};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocket* socket_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::array<uint8_t, CMSG_SPACE(sizeof(int) * kMaxFdsPerSocketMsg)>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ancillaryDataCtrlBuffer_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- friend class FdReadAncillaryDataCallback;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void enqueueFdsFromAncillaryData(struct ::msghdr& msg) noexcept;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ void setUpCallbacks() noexcept;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ FdSendMsgParamsCallback sendMsgCob_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::queue<SocketFds::Received>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- fdsQueue_; // must outlive readAncillaryDataCob_
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- FdReadAncillaryDataCallback readAncillaryDataCob_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #endif // !Windows
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+2.40.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/files/0003-Revert-Change-cloneToSendFrom-to-DFATAL-instead-of-C.patch b/devel/folly/files/0003-Revert-Change-cloneToSendFrom-to-DFATAL-instead-of-C.patch
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..f6574c228fc
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/files/0003-Revert-Change-cloneToSendFrom-to-DFATAL-instead-of-C.patch
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,37 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From 738fd9e20c79b63654e66669fd7d10e1d17ccfa9 Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: barracuda156 <vital.had@gmail.com>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Wed, 17 May 2023 14:39:26 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH 3/6] Revert "Change cloneToSendFrom to DFATAL instead of
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ CHECK"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 1f23eee52218d7de99c585444e84c279fb794d0d.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/SocketFds.h | 11 +++--------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 1 file changed, 3 insertions(+), 8 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/SocketFds.h folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 620a5dd0a..53707371f 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -96,15 +96,10 @@ class SocketFds final {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // `SocketFds` that are known to be in this state.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // - Invariant: `other` must be `ToSend`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ // - Cost: Cloning copies a vector into a new heap allocation.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void cloneToSendFromOrDfatal(const SocketFds& other) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ void cloneToSendFrom(const SocketFds& other) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!other.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto* fds = std::get_if<ToSend>(other.ptr_.get());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (UNLIKELY(fds == nullptr)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(DFATAL) << "SocketFds was in 'received' state, not cloning";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ptr_.reset();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ptr_ = std::make_unique<FdsVariant>(*fds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ auto* fds = CHECK_NOTNULL(std::get_if<ToSend>(other.ptr_.get()));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ ptr_ = std::make_unique<FdsVariant>(*fds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+2.40.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/files/0004-Revert-Add-const-to-help-with-thread-safety.patch b/devel/folly/files/0004-Revert-Add-const-to-help-with-thread-safety.patch
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..3fcb4b66a2b
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/files/0004-Revert-Add-const-to-help-with-thread-safety.patch
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,30 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From 3139135e63e36d6147f6a785dc9fa0874188cb13 Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: barracuda156 <vital.had@gmail.com>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Wed, 17 May 2023 14:39:45 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH 4/6] Revert "Add `const` to help with thread-safety"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit b492dbfb3ee6f1d151b9e5a978ebfec618946073.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/SocketFds.h | 6 +-----
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 1 file changed, 1 insertion(+), 5 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/SocketFds.h folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 53707371f..f160d78cb 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -48,11 +48,7 @@ namespace folly {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ class SocketFds final {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ using Received = std::vector<folly::File>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // These `shared_ptr`s are commonly be shared across threads -- and there
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // is no locking -- so `const` ensures thread-safety. Therefore, if
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // you're going to put your `File` into a `ToSend`, it's best to first
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // make your own copy `const`, too.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- using ToSend = std::vector<std::shared_ptr<const folly::File>>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ using ToSend = std::vector<std::shared_ptr<folly::File>>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ using FdsVariant = std::variant<Received, ToSend>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+2.40.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/files/0005-Revert-Unit-tests.patch b/devel/folly/files/0005-Revert-Unit-tests.patch
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..3da14cbfea2
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/files/0005-Revert-Unit-tests.patch
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,330 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From 94e534b75df21628aaedbf098374c03444c7ede6 Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: barracuda156 <vital.had@gmail.com>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Wed, 17 May 2023 14:40:42 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH 5/6] Revert "Unit tests"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 872c0332cea1cc8ca3bf8d0727e734654d855a3f.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ .../async/fdsock/test/AsyncFdSocketTest.cpp | 291 ------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/test/AsyncSocketTest.h | 3 +-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 2 files changed, 1 insertion(+), 293 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ delete mode 100644 folly/io/async/fdsock/test/AsyncFdSocketTest.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/test/AsyncFdSocketTest.cpp folly/io/async/fdsock/test/AsyncFdSocketTest.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+deleted file mode 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 9fce1d5d4..000000000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/test/AsyncFdSocketTest.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ /dev/null
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1,291 +0,0 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Copyright (c) Meta Platforms, Inc. and affiliates.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Licensed under the Apache License, Version 2.0 (the "License");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * you may not use this file except in compliance with the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * You may obtain a copy of the License at
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * http://www.apache.org/licenses/LICENSE-2.0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Unless required by applicable law or agreed to in writing, software
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * distributed under the License is distributed on an "AS IS" BASIS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * See the License for the specific language governing permissions and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * limitations under the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/io/async/fdsock/AsyncFdSocket.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/io/async/test/AsyncSocketTest.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/portability/GMock.h> // for matchers like HasSubstr
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/portability/GTest.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-using namespace folly;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// `AsyncFdSocket` is just a stub on Windows because its CMSG macros are busted
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-std::string getFdProcMagic(int fd) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- char magic[PATH_MAX];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PCHECK(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- -1 !=
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ::readlink(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- fmt::format("/proc/{}/fd/{}", getpid(), fd).c_str(),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- magic,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PATH_MAX));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return std::string(magic);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void checkFdsMatch(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const folly::SocketFds::ToSend& sFds,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const folly::SocketFds::Received& rFds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_EQ(sFds.size(), rFds.size());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (size_t i = 0; i < rFds.size(); ++i) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const auto& sfd = sFds[i]->fd();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const auto& rfd = rFds[i].fd();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // We should always receive with FD_CLOEXEC enabled
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- int flags = ::fcntl(rfd, F_GETFD);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PCHECK(-1 != flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_TRUE(flags & FD_CLOEXEC) << "Actual flags:" << flags;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Check that the two FDs appear identical in `/proc/PID/fd/FD`
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CHECK_EQ(getFdProcMagic(sfd), getFdProcMagic(rfd));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-folly::SocketFds::ToSend makeFdsToSend(size_t n) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- folly::SocketFds::ToSend sendFds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- while (sendFds.size() != n) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::array<int, 2> rawSendFds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Don't set FD_CLOEXEC here so it is extra-clear that the socket did it
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // (even though FD_CLOEXEC on this FD isn't coupled with its copy).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PCHECK(0 == ::pipe(rawSendFds.data()));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (int fd : rawSendFds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto f = std::make_shared<folly::File>(fd, /*ownsFd*/ true);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (sendFds.size() < n) { // handle odd `n`
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendFds.emplace_back(std::move(f));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CHECK_EQ(n, sendFds.size());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return sendFds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-struct AsyncFdSocketTest : public testing::Test {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocketTest()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : AsyncFdSocketTest{[]() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::array<NetworkSocket, 2> fds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PCHECK(0 == netops::socketpair(AF_UNIX, SOCK_STREAM, 0, fds.data()));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (int i = 0; i < 2; ++i) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PCHECK(0 == netops::set_socket_non_blocking(fds[i])) << i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return fds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }()} {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- explicit AsyncFdSocketTest(std::array<NetworkSocket, 2> fds)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : sendSock_{&evb_, fds[0]}, recvSock_{&evb_, fds[1]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- recvSock_.setReadCB(&rcb_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EventBase evb_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteCallback wcb_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocket sendSock_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ReadCallback rcb_; // NB: `~AsyncSocket` calls `rcb.readEOF`
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocket recvSock_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-TEST_F(AsyncFdSocketTest, FailNoData) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendSock_.writeChainWithFds(&wcb_, IOBuf::create(0), makeFdsToSend(1));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_THAT(wcb_.exception.what(), testing::HasSubstr("least 1 data byte"));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-TEST_F(AsyncFdSocketTest, FailTooManyFds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- char data = 'a'; // Need >= 1 data byte to send ancillary data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendSock_.writeChainWithFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &wcb_, IOBuf::wrapBuffer(&data, sizeof(data)), makeFdsToSend(254));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_EQ(EINVAL, wcb_.exception.getErrno());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-struct AsyncFdSocketSimpleRoundtripTest
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : public AsyncFdSocketTest,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- public testing::WithParamInterface<int> {};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-TEST_P(AsyncFdSocketSimpleRoundtripTest, WithNumFds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- int numFds = GetParam();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- char data = 'a'; // Need >= 1 data byte to send ancillary data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto sendFds = makeFdsToSend(numFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendSock_.writeChainWithFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &wcb_, IOBuf::wrapBuffer(&data, sizeof(data)), sendFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- evb_.loopOnce();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- rcb_.verifyData(&data, sizeof(data));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- rcb_.clearData();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto recvFds = recvSock_.popNextReceivedFds();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (0 == numFds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_FALSE(recvFds.has_value());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- checkFdsMatch(sendFds, *recvFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// Round-trip & verify various numbers of FDs with 1 byte of data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-INSTANTIATE_TEST_SUITE_P(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- VaryFdCount,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocketSimpleRoundtripTest,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- testing::Values(1, 0, 2, 253, 0, 3)); // 253 is the Linux max
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-struct WriteCountedAsyncFdSocket : public AsyncFdSocket {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- using AsyncFdSocket::AsyncFdSocket;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocket::WriteResult sendSocketMessage(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const iovec* vec,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- size_t count,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteFlags flags,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteRequestTag writeTag) override {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ++numWrites_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return AsyncSocket::sendSocketMessage(vec, count, flags, writeTag);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- size_t numWrites_{0};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// This test exists because without `FdSendMsgParamsCallback::wroteBytes`,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// we would be sending the same FDs repeatedly, whenever the data to be
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// written didn't fit in the `sendmsg` buffer and got sent in several
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// batches.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-TEST_F(AsyncFdSocketTest, MultiPartSend) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto sendFds = makeFdsToSend(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteCountedAsyncFdSocket sendSock{&evb_, sendSock_.detachNetworkSocket()};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Find the socket's "send" buffer size
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- socklen_t sendBufSize;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- socklen_t sizeOfSendBufSize = sizeof(sendBufSize);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- PCHECK(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- 0 ==
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- netops::getsockopt(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendSock.getNetworkSocket(),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SOL_SOCKET,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SO_SNDBUF,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &sendBufSize,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &sizeOfSendBufSize));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ASSERT_EQ(sizeof(sendBufSize), sizeOfSendBufSize);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Make the message too big for one `sendmsg`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- int numSendParts = 3;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::string data(numSendParts * sendBufSize, 'x');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendSock.writeChainWithFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &wcb_, IOBuf::wrapBuffer(data.data(), data.size()), sendFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // FDs are sent with the first send & received by the first receive
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- evb_.loopOnce();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- checkFdsMatch(sendFds, *recvSock_.popNextReceivedFds());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_EQ(1, sendSock.numWrites_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Receive the rest of the data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- while (rcb_.dataRead() < data.size()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- evb_.loopOnce();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- rcb_.verifyData(data.data(), data.size());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- rcb_.clearData();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_EQ(numSendParts, sendSock.numWrites_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // There are no more data or FDs
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- evb_.loopOnce(EVLOOP_NONBLOCK);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_EQ(0, rcb_.dataRead()) << "Leftover reads";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_FALSE(recvSock_.popNextReceivedFds().has_value()) << "Extra FDs";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-struct AsyncFdSocketSequenceRoundtripTest
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : public AsyncFdSocketTest,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- public testing::WithParamInterface<int> {};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-TEST_P(AsyncFdSocketSequenceRoundtripTest, WithDataSize) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- size_t dataSize = GetParam();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // The default `ReadCallback` has special-snowflake buffer management
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // that's annoying for this test. Secondarily, this exercises the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // "ReadVec" path.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ReadvCallback rcb(128, 3);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Avoid `readEOF` use-after-stack-scope in `~AsyncSocket`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SCOPE_EXIT { recvSock_.setReadCB(nullptr); };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- recvSock_.setReadCB(&rcb);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::queue<std::tuple<int, std::string, folly::SocketFds::ToSend>> sentQueue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Enqueue several writes before attempting reads
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- char msgFirstByte = 0; // The first byte of each data message is different.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (auto numFds : {0, 1, 0, 0, 2, 253, 253, 0, 5}) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // All but the first bytes are 255, while the first byte is a counter.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::string data(dataSize, '\377');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CHECK_LT(msgFirstByte, 254); // Don't collide with 255, don't overflow
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- data[0] = ++msgFirstByte;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto sendFds = makeFdsToSend(numFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendSock_.writeChainWithFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &wcb_, IOBuf::wrapBuffer(data.data(), data.size()), sendFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sentQueue.push({msgFirstByte, std::move(data), std::move(sendFds)});
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Read from the socket, and check that any batches of FDs arrive with the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // first byte of the matching data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- bool checkedFds{false};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // The max expected steps is ~3k: 1234567 / (3 * 128)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (int i = 0; i < 10000 && !sentQueue.empty(); ++i) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- evb_.loopOnce(EVLOOP_NONBLOCK);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- size_t dataRead = rcb.buf_->computeChainDataLength();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!dataRead) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!checkedFds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- checkedFds = true;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Ensure that FDs arrive with the first byte of the associated data
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ASSERT_EQ(std::get<0>(sentQueue.front()), rcb.buf_->data()[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const auto& sendFds = std::get<2>(sentQueue.front());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!sendFds.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto recvFds = recvSock_.popNextReceivedFds();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- checkFdsMatch(sendFds, *recvFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Move on to the next data chunk
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (dataRead >= std::get<1>(sentQueue.front()).size()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ASSERT_TRUE(checkedFds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- checkedFds = false;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto [firstByte, expectedData, _fds] = sentQueue.front();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto& buf = rcb.buf_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Check that the entire data string is as expected.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ASSERT_EQ(firstByte, buf->data()[0]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- buf->coalesce();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ASSERT_GE(buf->length(), expectedData.size());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ASSERT_EQ(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- 0, memcmp(expectedData.data(), buf->data(), expectedData.size()));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- buf->trimStart(expectedData.size());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sentQueue.pop();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_TRUE(sentQueue.empty()) << "Stuck reading?";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- evb_.loopOnce(EVLOOP_NONBLOCK);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_EQ(0, rcb.buf_->computeChainDataLength()) << "Leftover reads";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EXPECT_FALSE(recvSock_.popNextReceivedFds().has_value()) << "Extra FDs";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// Vary the data size to (hopefully) get a variety of chunking behaviors.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-INSTANTIATE_TEST_SUITE_P(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- VaryDataSize,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocketSequenceRoundtripTest,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- testing::Values(1, 12, 123, 1234, 12345, 123456, 1234567));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif // !Windows
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/test/AsyncSocketTest.h folly/io/async/test/AsyncSocketTest.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 1dcaaf23f..27f3c6d0c 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/test/AsyncSocketTest.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/test/AsyncSocketTest.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -258,12 +258,11 @@ class ReadvCallback : public folly::AsyncTransport::ReadCallback {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ CHECK_EQ(data, tmp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::unique_ptr<folly::IOBuf> buf_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ StateEnum state_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly::AsyncSocketException exception_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly::IOBufIovecBuilder queue_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ std::unique_ptr<folly::IOBuf> buf_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ const size_t len_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+2.40.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/folly/files/0006-Revert-writeChainWithFds-using-SendMsgParamsCallback.patch b/devel/folly/files/0006-Revert-writeChainWithFds-using-SendMsgParamsCallback.patch
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..da50c8d5005
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/folly/files/0006-Revert-writeChainWithFds-using-SendMsgParamsCallback.patch
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,539 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From 2d3a6253989cc93e8f8e5c83e567694f2c588b1a Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: barracuda156 <vital.had@gmail.com>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Wed, 17 May 2023 14:40:59 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH 6/6] Revert "`writeChainWithFds` using
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ `SendMsgParamsCallback`"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 62eeb799779cbc24b622ec8ce3501c7969d60bae.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/AsyncSocket.h | 2 +-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/AsyncFdSocket.cpp | 204 ------------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/AsyncFdSocket.h | 158 ------------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ folly/io/async/fdsock/SocketFds.h | 126 ---------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 4 files changed, 1 insertion(+), 489 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ delete mode 100644 folly/io/async/fdsock/AsyncFdSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ delete mode 100644 folly/io/async/fdsock/AsyncFdSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ delete mode 100644 folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/AsyncSocket.h folly/io/async/AsyncSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 9ff04ea6c..e65f1ba23 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/AsyncSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ folly/io/async/AsyncSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1657,7 +1657,7 @@ class AsyncSocket : public AsyncSocketTransport {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ bool containsZeroCopyBuf(folly::IOBuf* ptr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ void releaseZeroCopyBuf(uint32_t id);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- virtual void releaseIOBuf(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ void releaseIOBuf(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ std::unique_ptr<folly::IOBuf> buf, ReleaseIOBufCallback* callback);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ReadCode processZeroCopyRead();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/AsyncFdSocket.cpp folly/io/async/fdsock/AsyncFdSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+deleted file mode 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index d8cadc038..000000000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/AsyncFdSocket.cpp
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ /dev/null
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1,204 +0,0 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Copyright (c) Meta Platforms, Inc. and affiliates.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Licensed under the Apache License, Version 2.0 (the "License");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * you may not use this file except in compliance with the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * You may obtain a copy of the License at
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * http://www.apache.org/licenses/LICENSE-2.0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Unless required by applicable law or agreed to in writing, software
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * distributed under the License is distributed on an "AS IS" BASIS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * See the License for the specific language governing permissions and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * limitations under the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include "AsyncFdSocket.h"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-namespace folly {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-AsyncFdSocket::AsyncFdSocket(EventBase* evb)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : AsyncSocket(evb)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendMsgCob_(evb) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- setUpCallbacks();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-AsyncFdSocket::AsyncFdSocket(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EventBase* evb,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const folly::SocketAddress& address,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- uint32_t connectTimeout)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : AsyncFdSocket(evb) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- connect(nullptr, address, connectTimeout);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-AsyncFdSocket::AsyncFdSocket(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EventBase* evb, NetworkSocket fd, const folly::SocketAddress* peerAddress)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- : AsyncSocket(evb, fd, /* zeroCopyBufId */ 0, peerAddress)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendMsgCob_(evb) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- setUpCallbacks();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void AsyncFdSocket::writeChainWithFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteCallback* callback,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::unique_ptr<folly::IOBuf> buf,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds::ToSend fds,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteFlags flags) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK(fds.empty()) << "AsyncFdSocket cannot send FDs on Windows";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK_EQ(&sendMsgCob_, getSendMsgParamsCB());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (buf->empty() && !fds.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DestructorGuard dg(this);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException ex(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException::BAD_ARGS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- withAddr("Cannot send FDs without at least 1 data byte"));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return failWrite(__func__, callback, 0, ex);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!sendMsgCob_.registerFdsForWriteTag(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteRequestTag{buf.get()},
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::move(fds) // discarded on error
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- )) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Careful: this has no unittest coverage because I don't have a good
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // idea for how to cause this in a meaningful way. Should this be
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // a DCHECK? Plans that don't work:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // - Creating two `unique_ptr` from the same raw pointer would be
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // bad news bears for the test.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // - IOBuf recycling via getReleaseIOBufCallback() shouldn't be
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // possible either, since we unregister the tag in our `releaseIOBuf`
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // override below before releasing the IOBuf.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DestructorGuard dg(this);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException ex(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocketException::BAD_ARGS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- withAddr("Buffer was already owned by this socket"));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return failWrite(__func__, callback, 0, ex);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif // !Windows
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- writeChain(callback, std::move(buf), flags);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// The callbacks aren't defined on Windows -- the CMSG macros don't compile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void AsyncFdSocket::setUpCallbacks() noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocket::setSendMsgParamCB(&sendMsgCob_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void AsyncFdSocket::releaseIOBuf(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::unique_ptr<folly::IOBuf> buf, ReleaseIOBufCallback* callback) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- sendMsgCob_.destroyFdsForWriteTag(WriteRequestTag{buf.get()});
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncSocket::releaseIOBuf(std::move(buf), callback);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-std::pair<
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- size_t,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocket::FdSendMsgParamsCallback::WriteTagToFds::iterator>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-AsyncFdSocket::FdSendMsgParamsCallback::getCmsgSizeAndFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const AsyncSocket::WriteRequestTag& writeTag) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto it = writeTagToFds_.find(writeTag);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (it == writeTagToFds_.end()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return std::make_pair(0, it);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return std::make_pair(CMSG_SPACE(sizeof(int) * it->second.size()), it);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void AsyncFdSocket::FdSendMsgParamsCallback::getAncillaryData(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- folly::WriteFlags,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void* data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const WriteRequestTag& writeTag,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const bool /*byteEventsEnabled*/) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- eventBase_->dcheckIsInEventBaseThread();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto [cmsgSpace, fdsIt] = getCmsgSizeAndFds(writeTag);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CHECK_NE(0, cmsgSpace);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const auto& fds = fdsIt->second;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // NOT checking `fds.size() < SCM_MAX_FD` here because there's no way to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // propagate the error to the caller, and ultimately the write will fail
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // out with EINVAL anyway. The front-end that accepts FDs should check
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // this instead. If there is a debuggability issue, do add a LOG(ERROR).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ::msghdr msg{}; // Discarded, we just need to populate `data`
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- msg.msg_control = data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- msg.msg_controllen = cmsgSpace;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- struct ::cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CHECK_NOTNULL(cmsg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds.size());
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- cmsg->cmsg_level = SOL_SOCKET;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- cmsg->cmsg_type = SCM_RIGHTS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto* outFds = reinterpret_cast<int*>(CMSG_DATA(cmsg));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (size_t n = 0; n < fds.size(); ++n) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- outFds[n] = fds[n]->fd();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- VLOG(4) << "this=" << this << ", getAncillaryData() sending " << fds.size()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- << " FDs";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-uint32_t AsyncFdSocket::FdSendMsgParamsCallback::getAncillaryDataSize(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- folly::WriteFlags,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const WriteRequestTag& writeTag,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const bool /*byteEventsEnabled*/) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Not checking thread because `getAncillaryData` will follow.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Due to the unfortunate design of the callback API, this will run
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // again in `getAncillaryData`, let's pray for CPU caches here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto [size, _] = getCmsgSizeAndFds(writeTag);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return size;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void AsyncFdSocket::FdSendMsgParamsCallback::wroteBytes(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const WriteRequestTag& writeTag) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto nh = writeTagToFds_.extract(writeTag);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (nh.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // `AsyncSocket` will only call `wroteBytes` if `getAncillaryDataSize`
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // returned a nonzero value, so we'll never get here.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(DFATAL) << "wroteBytes without a matching `getAncillaryData`?";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- VLOG(5) << "this=" << this << ", FdSendMsgParamsCallback::wroteBytes() on "
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- << nh.mapped().size() << " FDs for tag " << writeTag;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-bool AsyncFdSocket::FdSendMsgParamsCallback::registerFdsForWriteTag(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteRequestTag writeTag, SocketFds::ToSend&& fds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- VLOG(5) << "this=" << this << ", registerFdsForWriteTag() on " << fds.size()
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- << " FDs for tag " << writeTag;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (writeTag.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return false; // no insertion, error: we require a nonempty tag
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto [it, inserted] = writeTagToFds_.try_emplace(writeTag, std::move(fds));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return inserted;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-void AsyncFdSocket::FdSendMsgParamsCallback::destroyFdsForWriteTag(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteRequestTag writeTag) noexcept {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto nh = writeTagToFds_.extract(writeTag);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (nh.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return; // Not every write has FDs; also, `wroteBytes` clears them.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- VLOG(5) << "this=" << this << ", destroyFdsForWriteTag() on "
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- << nh.mapped().size() << " FDs for tag " << writeTag;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif // !Windows
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-} // namespace folly
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/AsyncFdSocket.h folly/io/async/fdsock/AsyncFdSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+deleted file mode 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index d72d086ac..000000000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/AsyncFdSocket.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ /dev/null
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1,158 +0,0 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Copyright (c) Meta Platforms, Inc. and affiliates.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Licensed under the Apache License, Version 2.0 (the "License");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * you may not use this file except in compliance with the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * You may obtain a copy of the License at
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * http://www.apache.org/licenses/LICENSE-2.0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Unless required by applicable law or agreed to in writing, software
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * distributed under the License is distributed on an "AS IS" BASIS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * See the License for the specific language governing permissions and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * limitations under the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#pragma once
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/io/async/AsyncSocket.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/io/async/fdsock/SocketFds.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-namespace folly {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Intended for use with Unix sockets. Unlike regular `AsyncSocket`:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - Can send FDs via `writeChainWithFds` using socket ancillary data (see
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * `man cmsg`).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - Always attempts to receive FDs included in incoming ancillary data.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Groups of received FDs are enqueued to be retrieved via
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * `popNextReceivedFds`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - The "read ancillary data" and "sendmsg params" callbacks are built-in
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * are NOT customizable.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Implementation limitation: Unlike regular `AsyncSocket`, this currently
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * does not automatically send socket timestamping events. This could
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * easily be added, but seems of limited utility for Unix sockets.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-class AsyncFdSocket : public AsyncSocket {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- using UniquePtr = std::unique_ptr<AsyncSocket, Destructor>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Create a new unconnected AsyncSocket.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * connect() must later be called on this socket to establish a connection.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- explicit AsyncFdSocket(EventBase* evb);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Create a new AsyncSocket and begin the connection process.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Unlike `AsyncSocket`, lacks `useZeroCopy` since Unix sockets do not
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * support zero-copy.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocket(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EventBase* evb,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const folly::SocketAddress& address,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- uint32_t connectTimeout = 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Create a AsyncSocket from an already connected socket file descriptor.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Unlike `AsyncSocket`, lacks `zeroCopyBufId` since Unix sockets do not
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * support zero-copy.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- AsyncFdSocket(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- EventBase* evb,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- NetworkSocket fd,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const folly::SocketAddress* peerAddress = nullptr);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * `AsyncSocket::writeChain` analog that passes FDs as ancillary data over
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * the socket (see `man cmsg`).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Invariants:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - Max FDs per IOBuf: `SCM_MAX_FD` from include/net/scm.h, 253 for
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * effectively all of Linux history.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - FDs are received no earlier than the first data byte of the IOBuf,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * and no later than the last data byte. More specifically:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - The currently implemented behavior is that FDs arrive precisely
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * with the first data byte. This was efficient and good enough for
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Thrift Rocket transport, where each message knows whether it
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * expects FDs, and FDs are sent with the last data fragment of each
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * message.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - In other conceivable designs, it could be useful to pass FDs
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * with the last data byte instead, which could be implemented as an
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * optional write flag. In Thrift Rocket, this would minimize the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * buffering of FDs by the receiver, at the cost of more syscalls.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void writeChainWithFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteCallback*,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::unique_ptr<folly::IOBuf>,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds::ToSend,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteFlags flags = WriteFlags::NONE);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void setSendMsgParamCB(SendMsgParamsCallback*) override {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- LOG(DFATAL) << "AsyncFdSocket::setSendMsgParamCB is forbidden";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-// This uses no ancillary data callbacks on Windows, they wouldn't compile.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#if !defined(_WIN32)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protected:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void releaseIOBuf(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::unique_ptr<folly::IOBuf>, ReleaseIOBufCallback*) override;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- class FdSendMsgParamsCallback : public SendMsgParamsCallback {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- explicit FdSendMsgParamsCallback(folly::EventBase* evb) : eventBase_(evb) {}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void getAncillaryData(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- folly::WriteFlags,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void* data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const WriteRequestTag&,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const bool byteEventsEnabled) noexcept override;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- uint32_t getAncillaryDataSize(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- folly::WriteFlags,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const WriteRequestTag&,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const bool byteEventsEnabled) noexcept override;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void wroteBytes(const WriteRequestTag&) noexcept override;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protected:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- friend class AsyncFdSocket;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Returns true on success, false if the tag was already registered, or
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // has a null IOBuf* (both are usage error). The FDs are discarded on
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // error.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- bool registerFdsForWriteTag(WriteRequestTag, SocketFds::ToSend&&);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Called from `releaseIOBuf()` above, once we're sure that an IOBuf
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // will not be used for a write any more. This is a good time to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // discard the FDs associated with this write.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- //
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // CAREFUL: This may be invoked for IOBufs that never had a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // corresponding `getAncillaryData*` call.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void destroyFdsForWriteTag(WriteRequestTag) noexcept;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- using WriteTagToFds =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::unordered_map<WriteRequestTag, SocketFds::ToSend>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::pair<size_t, WriteTagToFds::iterator> getCmsgSizeAndFds(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const WriteRequestTag& writeTag) noexcept;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const folly::EventBase* eventBase_; // only for dcheckIsInEventBaseThread
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- WriteTagToFds writeTagToFds_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- };
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void setUpCallbacks() noexcept;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- FdSendMsgParamsCallback sendMsgCob_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#endif // !Windows
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-} // namespace folly
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git folly/io/async/fdsock/SocketFds.h folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+deleted file mode 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index f160d78cb..000000000
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- folly/io/async/fdsock/SocketFds.h
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ /dev/null
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -1,126 +0,0 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Copyright (c) Meta Platforms, Inc. and affiliates.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Licensed under the Apache License, Version 2.0 (the "License");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * you may not use this file except in compliance with the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * You may obtain a copy of the License at
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * http://www.apache.org/licenses/LICENSE-2.0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Unless required by applicable law or agreed to in writing, software
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * distributed under the License is distributed on an "AS IS" BASIS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * See the License for the specific language governing permissions and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * limitations under the License.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#pragma once
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <memory>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <variant>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <glog/logging.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#include <folly/File.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-namespace folly {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-/**
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * Represents an ordered collection of file descriptors. This union type
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * either contains:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - FDs to be sent on a socket -- with shared ownership, since the sender
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * may still need them, OR
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * - FDs just received, with sole ownership.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * This hides the variant of containers behind a `unique_ptr` so that the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * normal / fast path, which is not passing FDs, is as light as possible,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * adding just 8 bytes for a pointer.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * == Rationale ==
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * In order to send FDs over Unix sockets, Thrift plumbs them through a
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * variety of classes. Many of these can be used both for send & receive
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * operations (THeader, StreamPayload, etc).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * This is especially useful in regular Thrift request-response handler
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * methods, where the same THeader is used for consuming the received FDs,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * and sending back FDs with the response -- necessarily in that order.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-class SocketFds final {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- using Received = std::vector<folly::File>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- using ToSend = std::vector<std::shared_ptr<folly::File>>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- using FdsVariant = std::variant<Received, ToSend>;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- public:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds() = default;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds(SocketFds&& other) = default;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- template <class T>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- explicit SocketFds(T fds) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ptr_ = std::make_unique<FdsVariant>(std::move(fds));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds& operator=(SocketFds&& other) = default;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- bool empty() const { return !ptr_; }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- size_t size() const {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return std::visit([](auto&& v) { return v.size(); }, *ptr_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // These methods help ensure the right kind of data is being plumbed or
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // overwritten:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // fds.dcheckEmpty() = otherFds.dcheck{Received,ToSend}();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds& dcheckEmpty() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK(!ptr_);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return *this;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds& dcheckReceived() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK(std::holds_alternative<Received>(*ptr_));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return *this;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- SocketFds& dcheckToSend() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- DCHECK(std::holds_alternative<ToSend>(*ptr_));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return *this;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // Since ownership of `ToSend` FDs is shared, it is permissible to clone
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // `SocketFds` that are known to be in this state.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // - Invariant: `other` must be `ToSend`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // - Cost: Cloning copies a vector into a new heap allocation.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void cloneToSendFrom(const SocketFds& other) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!other.empty()) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto* fds = CHECK_NOTNULL(std::get_if<ToSend>(other.ptr_.get()));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ptr_ = std::make_unique<FdsVariant>(*fds);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- Received releaseReceived() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto fds = std::move(*CHECK_NOTNULL(std::get_if<Received>(ptr_.get())));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // NB: In the case of a Thrift server handler method that is receiving
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // and then sending back FDs using the same `SocketFds` object, this
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // deallocation (and subsequent allocation) could be avoided, e.g. by:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // - Without changing the API by having an additional `std::monostate`
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // representing the variant being empty. This has the downside of
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // holding on to allocations unnecessarily in other cases.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // - By adding `std::pair<Received, ToSend&> releaseReceivedAndSend()`.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- // This complicates the user experience.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ptr_.reset();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return fds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ToSend releaseToSend() {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- auto fds = std::move(*CHECK_NOTNULL(std::get_if<ToSend>(ptr_.get())));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ptr_.reset();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return fds;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- private:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- std::unique_ptr<FdsVariant> ptr_;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-};
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-} // namespace folly
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+2.40.1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span></pre><pre style='margin:0'>
</pre>