<pre style='margin:0'>
Perry E. Metzger (pmetzger) pushed a commit to branch master
in repository macports-ports.

</pre>
<p><a href="https://github.com/macports/macports-ports/commit/3e4ce606f96c3ee161c64c82e18ee7f7cef151e7">https://github.com/macports/macports-ports/commit/3e4ce606f96c3ee161c64c82e18ee7f7cef151e7</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 3e4ce606f96c3ee161c64c82e18ee7f7cef151e7
</span>Author: barracuda156 <vital.had@gmail.com>
AuthorDate: Fri Jan 12 07:22:38 2024 +0800

<span style='display:block; white-space:pre;color:#404040;'>    folly: update to 2024.01.08.00, drop patches reverting some commits
</span>---
 devel/folly/Portfile                               |  33 +-
 ...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 ---------------------
 devel/folly/files/patch-older-systems.diff         |  48 +-
 8 files changed, 34 insertions(+), 1300 deletions(-)

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

</pre>