<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>