[libc-commits] [libc] 7cea026 - [libc] Add a simple scope_exit wrapper and use it in socket tests (#192615)

via libc-commits libc-commits at lists.llvm.org
Wed May 6 02:37:32 PDT 2026


Author: Pavel Labath
Date: 2026-05-06T11:37:27+02:00
New Revision: 7cea026109ab3308cafae38dc5b1b89d8770fdab

URL: https://github.com/llvm/llvm-project/commit/7cea026109ab3308cafae38dc5b1b89d8770fdab
DIFF: https://github.com/llvm/llvm-project/commit/7cea026109ab3308cafae38dc5b1b89d8770fdab.diff

LOG: [libc] Add a simple scope_exit wrapper and use it in socket tests (#192615)

This is slightly different from the other CPP reimplementations in that
the real scope_exit is only an experimental C++ class. If that's an
issue, I'm happy to put the class somewhere else.

It could probably be used in more places, but right now I'm adding it to
socket tests, as that's what I'm familiar with. It (mostly -- it doesn't
help with crashes) solves the issue where a failing test does not clean
up the unix domain socket, which then fails the test on the subsequent
run.

Added: 
    libc/src/__support/CPP/scope.h
    libc/test/src/__support/CPP/scope_test.cpp

Modified: 
    libc/src/__support/CPP/CMakeLists.txt
    libc/test/src/__support/CPP/CMakeLists.txt
    libc/test/src/sys/socket/linux/CMakeLists.txt
    libc/test/src/sys/socket/linux/bind_test.cpp
    libc/test/src/sys/socket/linux/connect_accept_test.cpp
    libc/test/src/sys/socket/linux/listen_test.cpp
    libc/test/src/sys/socket/linux/send_recv_test.cpp
    libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp
    libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp
    libc/test/src/sys/socket/linux/socketopt_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index bdfbc6151c773..03e21ac6c80ca 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -214,6 +214,14 @@ add_object_library(
     libc.src.__support.macros.properties.os
 )
 
+add_header_library(
+  scope
+  HDRS
+    scope.h
+  DEPENDS
+    .utility
+)
+
 add_header_library(
   tuple
   HDRS

diff  --git a/libc/src/__support/CPP/scope.h b/libc/src/__support/CPP/scope.h
new file mode 100644
index 0000000000000..95abc969883ba
--- /dev/null
+++ b/libc/src/__support/CPP/scope.h
@@ -0,0 +1,54 @@
+//===-- Standalone implementation of experimental/scope ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_SCOPE_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_SCOPE_H
+
+#include "src/__support/CPP/utility/forward.h"
+#include "src/__support/CPP/utility/move.h"
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+// A reimplementation of std::experimental::scope_exit from the C++ library
+// fundamentals TS v3
+template <typename EF> class scope_exit {
+  EF exit_function;
+  bool execute_on_destruction;
+
+public:
+  template <typename Fn>
+  LIBC_INLINE explicit scope_exit(Fn &&fn)
+      : exit_function(cpp::forward<Fn>(fn)), execute_on_destruction(true) {}
+
+  LIBC_INLINE scope_exit(scope_exit &&other)
+      : exit_function(cpp::move(other.exit_function)),
+        execute_on_destruction(other.execute_on_destruction) {
+    other.release();
+  }
+
+  scope_exit(const scope_exit &) = delete;
+  scope_exit &operator=(const scope_exit &) = delete;
+  scope_exit &operator=(scope_exit &&) = delete;
+
+  LIBC_INLINE ~scope_exit() {
+    if (execute_on_destruction)
+      exit_function();
+  }
+
+  LIBC_INLINE void release() { execute_on_destruction = false; }
+};
+
+template <typename EF> scope_exit(EF) -> scope_exit<EF>;
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_SCOPE_H

diff  --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt
index 430cd7b136c69..1d47455dcd31f 100644
--- a/libc/test/src/__support/CPP/CMakeLists.txt
+++ b/libc/test/src/__support/CPP/CMakeLists.txt
@@ -140,6 +140,16 @@ add_libc_test(
     libc.src.__support.CPP.tuple
 )
 
+add_libc_test(
+  scope_test
+  SUITE
+    libc-cpp-utils-tests
+  SRCS
+    scope_test.cpp
+  DEPENDS
+    libc.src.__support.CPP.scope
+)
+
 add_libc_test(
   span_test
   SUITE

diff  --git a/libc/test/src/__support/CPP/scope_test.cpp b/libc/test/src/__support/CPP/scope_test.cpp
new file mode 100644
index 0000000000000..c74bf218f91fc
--- /dev/null
+++ b/libc/test/src/__support/CPP/scope_test.cpp
@@ -0,0 +1,49 @@
+//===-- Unittests for scope_exit ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/CPP/scope.h"
+#include "src/__support/CPP/utility/move.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::cpp::scope_exit;
+
+TEST(LlvmLibcScopeExitTest, Basic) {
+  bool called = false;
+  {
+    scope_exit cleanup([&called] { called = true; });
+    ASSERT_FALSE(called);
+  }
+  ASSERT_TRUE(called);
+}
+
+TEST(LlvmLibcScopeExitTest, Release) {
+  bool called = false;
+  {
+    scope_exit cleanup([&called] { called = true; });
+    ASSERT_FALSE(called);
+    cleanup.release();
+  }
+  ASSERT_FALSE(called);
+}
+
+TEST(LlvmLibcScopeExitTest, Move) {
+  bool called = false;
+  {
+    scope_exit cleanup1([&called] { called = true; });
+    {
+      scope_exit cleanup2(LIBC_NAMESPACE::cpp::move(cleanup1));
+      ASSERT_FALSE(called);
+    }
+    // cleanup2 goes out of scope here, should call the function.
+    ASSERT_TRUE(called);
+    called = false; // reset
+  }
+  // cleanup1 goes out of scope here, but it was moved from, so it shouldn't
+  // call.
+  ASSERT_FALSE(called);
+}

diff  --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index 636c5f316eb99..e29140ee06b24 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -46,6 +46,7 @@ add_libc_unittest(
     libc.src.sys.socket.bind
     libc.src.stdio.remove
     libc.src.unistd.close
+    libc.src.__support.CPP.scope
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
@@ -73,6 +74,7 @@ add_libc_unittest(
     libc.src.sys.socket.socket
     libc.src.stdio.remove
     libc.src.unistd.close
+    libc.src.__support.CPP.scope
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
@@ -94,6 +96,7 @@ add_libc_unittest(
     libc.src.sys.socket.listen
     libc.src.stdio.remove
     libc.src.unistd.close
+    libc.src.__support.CPP.scope
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
@@ -115,6 +118,7 @@ add_libc_unittest(
     libc.src.sys.socket.socket
     libc.src.unistd.close
     libc.src.unistd.pipe
+    libc.src.__support.CPP.scope
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
@@ -147,6 +151,7 @@ add_libc_unittest(
     libc.src.sys.socket.send
     libc.src.sys.socket.recv
     libc.src.unistd.close
+    libc.src.__support.CPP.scope
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
@@ -164,6 +169,7 @@ add_libc_unittest(
     libc.src.sys.socket.sendto
     libc.src.sys.socket.recvfrom
     libc.src.unistd.close
+    libc.src.__support.CPP.scope
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )
@@ -187,6 +193,7 @@ add_libc_unittest(
     libc.src.sys.socket.sendmsg
     libc.src.sys.socket.recvmsg
     libc.src.unistd.close
+    libc.src.__support.CPP.scope
     libc.test.UnitTest.ErrnoCheckingTest
     libc.test.UnitTest.ErrnoSetterMatcher
 )

diff  --git a/libc/test/src/sys/socket/linux/bind_test.cpp b/libc/test/src/sys/socket/linux/bind_test.cpp
index 231982a7c787a..ff0b7d1f44077 100644
--- a/libc/test/src/sys/socket/linux/bind_test.cpp
+++ b/libc/test/src/sys/socket/linux/bind_test.cpp
@@ -14,6 +14,7 @@
 #include "src/stdio/remove.h"
 #include "src/unistd/close.h"
 
+#include "src/__support/CPP/scope.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
@@ -30,6 +31,8 @@ TEST_F(LlvmLibcBindTest, BindLocalSocket) {
   int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_DGRAM, 0);
   ASSERT_GE(sock, 0);
   ASSERT_ERRNO_SUCCESS();
+  LIBC_NAMESPACE::cpp::scope_exit close_sock(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0)); });
 
   struct sockaddr_un my_addr;
   ASSERT_TRUE(LIBC_NAMESPACE::testing::make_sockaddr_un(SOCK_PATH, my_addr));
@@ -38,6 +41,5 @@ TEST_F(LlvmLibcBindTest, BindLocalSocket) {
       LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
                            sizeof(struct sockaddr_un)),
       Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0));
   ASSERT_THAT(LIBC_NAMESPACE::remove(SOCK_PATH), Succeeds(0));
 }

diff  --git a/libc/test/src/sys/socket/linux/connect_accept_test.cpp b/libc/test/src/sys/socket/linux/connect_accept_test.cpp
index fe3ff05b351df..97cf822936cc2 100644
--- a/libc/test/src/sys/socket/linux/connect_accept_test.cpp
+++ b/libc/test/src/sys/socket/linux/connect_accept_test.cpp
@@ -20,6 +20,7 @@
 #include "src/sys/socket/socket.h"
 #include "src/unistd/close.h"
 
+#include "src/__support/CPP/scope.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/src/sys/socket/linux/socket_test_support.h"
@@ -28,6 +29,7 @@ using LIBC_NAMESPACE::testing::make_sockaddr_un;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
 using LlvmLibcConnectAcceptTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::scope_exit;
 
 TEST_F(LlvmLibcConnectAcceptTest, ConnectLocalSocket) {
   const char *CONNECT_FILE = "connect_file.test";
@@ -43,43 +45,52 @@ TEST_F(LlvmLibcConnectAcceptTest, ConnectLocalSocket) {
   int accepting_socket = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
   ASSERT_GE(accepting_socket, 0);
   ASSERT_ERRNO_SUCCESS();
+  scope_exit close_accepting_socket([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::close(accepting_socket), Succeeds(0));
+  });
 
   ASSERT_THAT(LIBC_NAMESPACE::bind(
                   accepting_socket,
                   reinterpret_cast<const struct sockaddr *>(&accept_addr),
                   sizeof(struct sockaddr_un)),
               Succeeds(0));
-
-  int connecting_socket = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
-  ASSERT_GE(connecting_socket, 0);
-  ASSERT_ERRNO_SUCCESS();
-
-  // These should fail as the other side is not listen()ing yet.
-  ASSERT_THAT(LIBC_NAMESPACE::accept(accepting_socket, nullptr, nullptr),
-              Fails(EINVAL));
-  ASSERT_THAT(LIBC_NAMESPACE::connect(
-                  connecting_socket,
-                  reinterpret_cast<const struct sockaddr *>(&accept_addr),
-                  sizeof(struct sockaddr_un)),
-              Fails(ECONNREFUSED));
-
-  ASSERT_THAT(LIBC_NAMESPACE::listen(accepting_socket, 1), Succeeds(0));
-
-  ASSERT_THAT(LIBC_NAMESPACE::connect(
-                  connecting_socket,
-                  reinterpret_cast<const struct sockaddr *>(&accept_addr),
-                  sizeof(struct sockaddr_un)),
-              Succeeds(0));
-
-  int accepted_socket =
-      LIBC_NAMESPACE::accept(accepting_socket, nullptr, nullptr);
-  ASSERT_GE(accepted_socket, 0);
-  ASSERT_ERRNO_SUCCESS();
-  ASSERT_THAT(LIBC_NAMESPACE::close(accepted_socket), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::close(connecting_socket), Succeeds(0));
+  scope_exit remove_accept_path(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::remove(ACCEPT_PATH), Succeeds(0)); });
+
+  {
+    int connecting_socket = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+    ASSERT_GE(connecting_socket, 0);
+    ASSERT_ERRNO_SUCCESS();
+    scope_exit close_connecting_socket([&] {
+      ASSERT_THAT(LIBC_NAMESPACE::close(connecting_socket), Succeeds(0));
+    });
+
+    // These should fail as the other side is not listen()ing yet.
+    ASSERT_THAT(LIBC_NAMESPACE::accept(accepting_socket, nullptr, nullptr),
+                Fails(EINVAL));
+    ASSERT_THAT(LIBC_NAMESPACE::connect(
+                    connecting_socket,
+                    reinterpret_cast<const struct sockaddr *>(&accept_addr),
+                    sizeof(struct sockaddr_un)),
+                Fails(ECONNREFUSED));
+
+    ASSERT_THAT(LIBC_NAMESPACE::listen(accepting_socket, 1), Succeeds(0));
+
+    ASSERT_THAT(LIBC_NAMESPACE::connect(
+                    connecting_socket,
+                    reinterpret_cast<const struct sockaddr *>(&accept_addr),
+                    sizeof(struct sockaddr_un)),
+                Succeeds(0));
+
+    int accepted_socket =
+        LIBC_NAMESPACE::accept(accepting_socket, nullptr, nullptr);
+    ASSERT_GE(accepted_socket, 0);
+    ASSERT_ERRNO_SUCCESS();
+    ASSERT_THAT(LIBC_NAMESPACE::close(accepted_socket), Succeeds(0));
+  }
 
   // Now try connecting again, but pass a non-nullptr address to accept().
-  connecting_socket = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+  int connecting_socket = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
   ASSERT_GE(connecting_socket, 0);
   ASSERT_ERRNO_SUCCESS();
 
@@ -88,6 +99,8 @@ TEST_F(LlvmLibcConnectAcceptTest, ConnectLocalSocket) {
                   reinterpret_cast<const struct sockaddr *>(&connect_addr),
                   sizeof(struct sockaddr_un)),
               Succeeds(0));
+  scope_exit remove_connect_path(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::remove(CONNECT_PATH), Succeeds(0)); });
 
   ASSERT_THAT(LIBC_NAMESPACE::connect(
                   connecting_socket,
@@ -97,7 +110,7 @@ TEST_F(LlvmLibcConnectAcceptTest, ConnectLocalSocket) {
 
   struct sockaddr_un accepted_addr;
   socklen_t accepted_addr_len = sizeof(accepted_addr);
-  accepted_socket = LIBC_NAMESPACE::accept(
+  int accepted_socket = LIBC_NAMESPACE::accept(
       accepting_socket, reinterpret_cast<struct sockaddr *>(&accepted_addr),
       &accepted_addr_len);
   ASSERT_GE(accepted_socket, 0);
@@ -106,11 +119,6 @@ TEST_F(LlvmLibcConnectAcceptTest, ConnectLocalSocket) {
   ASSERT_THAT((LIBC_NAMESPACE::testing::SocketAddress{accepted_addr,
                                                       accepted_addr_len}),
               LIBC_NAMESPACE::testing::MatchesAddress(CONNECT_PATH));
-
-  ASSERT_THAT(LIBC_NAMESPACE::close(accepting_socket), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::close(connecting_socket), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::remove(ACCEPT_PATH), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::remove(CONNECT_PATH), Succeeds(0));
 }
 
 TEST_F(LlvmLibcConnectAcceptTest, Accept4Flags) {

diff  --git a/libc/test/src/sys/socket/linux/listen_test.cpp b/libc/test/src/sys/socket/linux/listen_test.cpp
index cf78c57de7896..4c1c7d7f223b9 100644
--- a/libc/test/src/sys/socket/linux/listen_test.cpp
+++ b/libc/test/src/sys/socket/linux/listen_test.cpp
@@ -15,6 +15,7 @@
 #include "src/stdio/remove.h"
 #include "src/unistd/close.h"
 
+#include "src/__support/CPP/scope.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/src/sys/socket/linux/socket_test_support.h"
@@ -22,6 +23,7 @@
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
 using LlvmLibcListenTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::scope_exit;
 
 TEST_F(LlvmLibcListenTest, ListenLocalSocket) {
 
@@ -31,6 +33,8 @@ TEST_F(LlvmLibcListenTest, ListenLocalSocket) {
   int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
   ASSERT_GE(sock, 0);
   ASSERT_ERRNO_SUCCESS();
+  scope_exit close_sock(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0)); });
 
   struct sockaddr_un my_addr;
   ASSERT_TRUE(LIBC_NAMESPACE::testing::make_sockaddr_un(SOCK_PATH, my_addr));
@@ -39,11 +43,10 @@ TEST_F(LlvmLibcListenTest, ListenLocalSocket) {
       LIBC_NAMESPACE::bind(sock, reinterpret_cast<struct sockaddr *>(&my_addr),
                            sizeof(struct sockaddr_un)),
       Succeeds(0));
+  scope_exit remove_sock_path(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::remove(SOCK_PATH), Succeeds(0)); });
 
   ASSERT_THAT(LIBC_NAMESPACE::listen(sock, 5), Succeeds(0));
-
-  ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::remove(SOCK_PATH), Succeeds(0));
 }
 
 TEST_F(LlvmLibcListenTest, ListenFails) {

diff  --git a/libc/test/src/sys/socket/linux/send_recv_test.cpp b/libc/test/src/sys/socket/linux/send_recv_test.cpp
index 6210c15810a9c..ce1a72795b584 100644
--- a/libc/test/src/sys/socket/linux/send_recv_test.cpp
+++ b/libc/test/src/sys/socket/linux/send_recv_test.cpp
@@ -13,6 +13,7 @@
 
 #include "src/unistd/close.h"
 
+#include "src/__support/CPP/scope.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
@@ -29,6 +30,10 @@ TEST_F(LlvmLibcSendRecvTest, SucceedsWithSocketPair) {
 
   ASSERT_THAT(LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair),
               Succeeds(0));
+  LIBC_NAMESPACE::cpp::scope_exit close_sockpair([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
+  });
 
   ASSERT_THAT(LIBC_NAMESPACE::send(sockpair[0], TEST_MESSAGE, MESSAGE_LEN, 0),
               Succeeds(static_cast<ssize_t>(MESSAGE_LEN)));
@@ -39,10 +44,6 @@ TEST_F(LlvmLibcSendRecvTest, SucceedsWithSocketPair) {
               Succeeds(static_cast<ssize_t>(MESSAGE_LEN)));
 
   ASSERT_STREQ(buffer, TEST_MESSAGE);
-
-  // close both ends of the socket
-  ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
 }
 
 TEST_F(LlvmLibcSendRecvTest, MsgFlagsTest) {

diff  --git a/libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp b/libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp
index fcc71ab1c3994..0941c8eac4570 100644
--- a/libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp
+++ b/libc/test/src/sys/socket/linux/sendmsg_recvmsg_test.cpp
@@ -19,6 +19,7 @@
 
 #include "src/unistd/close.h"
 
+#include "src/__support/CPP/scope.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/LibcTest.h"
@@ -36,6 +37,10 @@ TEST_F(LlvmLibcSendMsgRecvMsgTest, SucceedsWithSocketPair) {
 
   ASSERT_THAT(LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair),
               Succeeds(0));
+  LIBC_NAMESPACE::cpp::scope_exit close_sockpair([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
+  });
 
   iovec send_msg_text;
   send_msg_text.iov_base =
@@ -73,10 +78,6 @@ TEST_F(LlvmLibcSendMsgRecvMsgTest, SucceedsWithSocketPair) {
               Succeeds(static_cast<ssize_t>(MESSAGE_LEN)));
 
   ASSERT_STREQ(buffer, TEST_MESSAGE);
-
-  // close both ends of the socket
-  ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
 }
 
 TEST_F(LlvmLibcSendMsgRecvMsgTest, CmsgDetails) {

diff  --git a/libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp b/libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp
index cd718fecef485..e10e572159a8c 100644
--- a/libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp
+++ b/libc/test/src/sys/socket/linux/sendto_recvfrom_test.cpp
@@ -12,6 +12,7 @@
 
 #include "src/unistd/close.h"
 
+#include "src/__support/CPP/scope.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
@@ -30,6 +31,10 @@ TEST_F(LlvmLibcSendToRecvFromTest, SucceedsWithSocketPair) {
 
   ASSERT_THAT(LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair),
               Succeeds(0));
+  LIBC_NAMESPACE::cpp::scope_exit close_sockpair([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
+  });
 
   ASSERT_THAT(LIBC_NAMESPACE::sendto(sockpair[0], TEST_MESSAGE, MESSAGE_LEN, 0,
                                      nullptr, 0),
@@ -42,10 +47,6 @@ TEST_F(LlvmLibcSendToRecvFromTest, SucceedsWithSocketPair) {
               Succeeds(static_cast<ssize_t>(MESSAGE_LEN)));
 
   ASSERT_STREQ(buffer, TEST_MESSAGE);
-
-  // close both ends of the socket
-  ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
-  ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
 }
 
 TEST_F(LlvmLibcSendToRecvFromTest, SendToFails) {

diff  --git a/libc/test/src/sys/socket/linux/socketopt_test.cpp b/libc/test/src/sys/socket/linux/socketopt_test.cpp
index 0e132a877d0c7..5dcccf1095ae5 100644
--- a/libc/test/src/sys/socket/linux/socketopt_test.cpp
+++ b/libc/test/src/sys/socket/linux/socketopt_test.cpp
@@ -15,6 +15,7 @@
 #include "src/unistd/close.h"
 #include "src/unistd/pipe.h"
 
+#include "src/__support/CPP/scope.h"
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
@@ -23,10 +24,13 @@
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
 using LlvmLibcSocketOptTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::scope_exit;
 
 TEST_F(LlvmLibcSocketOptTest, BasicSocketOpt) {
   int sock = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
   ASSERT_GE(sock, 0);
+  scope_exit close_sock(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0)); });
 
   int optval = 0;
   socklen_t optlen = sizeof(optval);
@@ -73,13 +77,13 @@ TEST_F(LlvmLibcSocketOptTest, BasicSocketOpt) {
   ASSERT_EQ(lin.l_onoff, 1);
   ASSERT_EQ(lin.l_linger, 5);
   ASSERT_EQ(optlen, static_cast<socklen_t>(sizeof(lin)));
-
-  ASSERT_THAT(LIBC_NAMESPACE::close(sock), Succeeds(0));
 }
 
 TEST_F(LlvmLibcSocketOptTest, NotASocket) {
   int fds[2];
   ASSERT_THAT(LIBC_NAMESPACE::pipe(fds), Succeeds(0));
+  scope_exit close_fd0(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(fds[0]), Succeeds(0)); });
   ASSERT_THAT(LIBC_NAMESPACE::close(fds[1]), Succeeds(0));
 
   int optval = 1;
@@ -91,7 +95,6 @@ TEST_F(LlvmLibcSocketOptTest, NotASocket) {
   ASSERT_THAT(LIBC_NAMESPACE::getsockopt(fds[0], SOL_SOCKET, SO_KEEPALIVE,
                                          &optval, &optlen),
               Fails(ENOTSOCK));
-  ASSERT_THAT(LIBC_NAMESPACE::close(fds[0]), Succeeds(0));
 }
 
 TEST_F(LlvmLibcSocketOptTest, InvalidSocket) {


        


More information about the libc-commits mailing list