[libc-commits] [libc] [libc] Implement accept4 on linux (PR #192927)
Pavel Labath via libc-commits
libc-commits at lists.llvm.org
Mon Apr 20 03:06:52 PDT 2026
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/192927
>From 88988f992493e722589fb6d8d912d88ba43abe98 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Mon, 20 Apr 2026 09:53:05 +0000
Subject: [PATCH 1/2] [libc] Implement accept4(2) on linux
Testing funcitonality by checking the flags on the returned FD.
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
.../linux/sys-socket-macros.h | 3 ++
libc/include/sys/socket.yaml | 9 ++++
.../linux/syscall_wrappers/CMakeLists.txt | 14 +++++
libc/src/sys/socket/CMakeLists.txt | 7 +++
libc/src/sys/socket/linux/CMakeLists.txt | 14 +++++
libc/test/src/sys/socket/linux/CMakeLists.txt | 3 ++
.../sys/socket/linux/connect_accept_test.cpp | 53 +++++++++++++++++++
10 files changed, 106 insertions(+)
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 87bd5461496b3..15d7c799883c0 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -1214,6 +1214,7 @@ if(LLVM_LIBC_FULL_BUILD)
# sys/socket.h entrypoints
libc.src.sys.socket.accept
+ libc.src.sys.socket.accept4
libc.src.sys.socket.bind
libc.src.sys.socket.connect
libc.src.sys.socket.getsockopt
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index ea117c1d83c24..554641d4fc5d4 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -1348,6 +1348,7 @@ if(LLVM_LIBC_FULL_BUILD)
# sys/socket.h entrypoints
libc.src.sys.socket.accept
+ libc.src.sys.socket.accept4
libc.src.sys.socket.bind
libc.src.sys.socket.connect
libc.src.sys.socket.getsockopt
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 5c69c8808b2c1..5ce78e755a110 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -1422,6 +1422,7 @@ if(LLVM_LIBC_FULL_BUILD)
# sys/socket.h entrypoints
libc.src.sys.socket.accept
+ libc.src.sys.socket.accept4
libc.src.sys.socket.socket
libc.src.sys.socket.bind
libc.src.sys.socket.connect
diff --git a/libc/include/llvm-libc-macros/linux/sys-socket-macros.h b/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
index 5a5cfd578dcbf..b7c52b9b0c349 100644
--- a/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
+++ b/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
@@ -25,6 +25,9 @@
#define SOCK_SEQPACKET 5
#define SOCK_PACKET 10
+#define SOCK_CLOEXEC 0x80000
+#define SOCK_NONBLOCK 0x800
+
#define SOL_SOCKET 1
#define SO_DEBUG 1
diff --git a/libc/include/sys/socket.yaml b/libc/include/sys/socket.yaml
index 28a81328a3559..e6b93827e3646 100644
--- a/libc/include/sys/socket.yaml
+++ b/libc/include/sys/socket.yaml
@@ -24,6 +24,15 @@ functions:
- type: int
- type: struct sockaddr *__restrict
- type: socklen_t *__restrict
+ - name: accept4
+ standards:
+ - Linux
+ return_type: int
+ arguments:
+ - type: int
+ - type: struct sockaddr *__restrict
+ - type: socklen_t *__restrict
+ - type: int
- name: bind
standards:
- POSIX
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index f00fa9668afe7..049eeac913780 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -38,6 +38,20 @@ add_header_library(
libc.include.sys_syscall
)
+add_header_library(
+ accept4
+ HDRS
+ accept4.h
+ DEPENDS
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.libc_errno
+ libc.src.__support.macros.config
+ libc.hdr.types.socklen_t
+ libc.hdr.types.struct_sockaddr
+ libc.include.sys_syscall
+)
+
add_header_library(
connect
HDRS
diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt
index 50558c667c78a..70be4c048d90f 100644
--- a/libc/src/sys/socket/CMakeLists.txt
+++ b/libc/src/sys/socket/CMakeLists.txt
@@ -16,6 +16,13 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.accept
)
+add_entrypoint_object(
+ accept4
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.accept4
+)
+
add_entrypoint_object(
bind
ALIAS
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index c63a8e1fafe19..417a00e552f82 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -38,6 +38,20 @@ add_entrypoint_object(
libc.src.errno.errno
)
+add_entrypoint_object(
+ accept4
+ SRCS
+ accept4.cpp
+ HDRS
+ ../accept4.h
+ DEPENDS
+ libc.include.sys_socket
+ libc.src.__support.OSUtil.osutil
+ libc.hdr.types.struct_sockaddr
+ libc.hdr.types.socklen_t
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
connect
SRCS
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index af0a46e9a06bb..10ca9039f5b9d 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -42,11 +42,14 @@ add_libc_unittest(
connect_accept_test.cpp
DEPENDS
libc.include.sys_socket
+ libc.hdr.fcntl_macros
libc.hdr.sys_socket_macros
libc.hdr.types.size_t
libc.hdr.types.struct_sockaddr_un
libc.src.errno.errno
+ libc.src.fcntl.fcntl
libc.src.sys.socket.accept
+ libc.src.sys.socket.accept4
libc.src.sys.socket.bind
libc.src.sys.socket.connect
libc.src.sys.socket.listen
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 b95992d030324..c523d470f616f 100644
--- a/libc/test/src/sys/socket/linux/connect_accept_test.cpp
+++ b/libc/test/src/sys/socket/linux/connect_accept_test.cpp
@@ -6,10 +6,13 @@
//
//===----------------------------------------------------------------------===//
+#include "hdr/fcntl_macros.h"
#include "hdr/sys_socket_macros.h"
#include "hdr/types/size_t.h"
#include "hdr/types/struct_sockaddr_un.h"
+#include "src/fcntl/fcntl.h"
#include "src/sys/socket/accept.h"
+#include "src/sys/socket/accept4.h"
#include "src/sys/socket/bind.h"
#include "src/sys/socket/connect.h"
#include "src/sys/socket/listen.h"
@@ -123,3 +126,53 @@ TEST_F(LlvmLibcConnectAcceptTest, ConnectLocalSocket) {
ASSERT_THAT(LIBC_NAMESPACE::remove(ACCEPT_PATH), Succeeds(0));
ASSERT_THAT(LIBC_NAMESPACE::remove(CONNECT_PATH), Succeeds(0));
}
+
+TEST_F(LlvmLibcConnectAcceptTest, Accept4Flags) {
+ const char *ACCEPT_FILE = "accept4_file.test";
+ auto ACCEPT_PATH = libc_make_test_file_path(ACCEPT_FILE);
+ ASSERT_LT(LIBC_NAMESPACE::strlen(ACCEPT_PATH), MAX_SOCKET_PATH);
+ const struct sockaddr_un ACCEPT_ADDR = make_sockaddr(ACCEPT_PATH);
+
+ int accepting_socket = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_GE(accepting_socket, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ ASSERT_THAT(LIBC_NAMESPACE::bind(
+ accepting_socket,
+ reinterpret_cast<const struct sockaddr *>(&ACCEPT_ADDR),
+ sizeof(struct sockaddr_un)),
+ Succeeds(0));
+
+ ASSERT_THAT(LIBC_NAMESPACE::listen(accepting_socket, 1), Succeeds(0));
+
+ int connecting_socket = LIBC_NAMESPACE::socket(AF_UNIX, SOCK_STREAM, 0);
+ ASSERT_GE(connecting_socket, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ 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::accept4(
+ accepting_socket, nullptr, nullptr, SOCK_CLOEXEC | SOCK_NONBLOCK);
+ ASSERT_GE(accepted_socket, 0);
+ ASSERT_ERRNO_SUCCESS();
+
+ ASSERT_THAT(LIBC_NAMESPACE::close(connecting_socket), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::close(accepting_socket), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::remove(ACCEPT_PATH), Succeeds(0));
+
+ // Check FD_CLOEXEC
+ int fd_flags = LIBC_NAMESPACE::fcntl(accepted_socket, F_GETFD);
+ ASSERT_GE(fd_flags, 0);
+ ASSERT_NE(fd_flags & FD_CLOEXEC, 0);
+
+ // Check O_NONBLOCK
+ int fl_flags = LIBC_NAMESPACE::fcntl(accepted_socket, F_GETFL);
+ ASSERT_GE(fl_flags, 0);
+ ASSERT_NE(fl_flags & O_NONBLOCK, 0);
+
+ ASSERT_THAT(LIBC_NAMESPACE::close(accepted_socket), Succeeds(0));
+}
>From 8938a0135626555c1f1b4974d234f87e7f2c664e Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Mon, 20 Apr 2026 10:04:59 +0000
Subject: [PATCH 2/2] add missing files
---
.../OSUtil/linux/syscall_wrappers/accept4.h | 49 +++++++++++++++++++
libc/src/sys/socket/accept4.h | 24 +++++++++
libc/src/sys/socket/linux/accept4.cpp | 31 ++++++++++++
3 files changed, 104 insertions(+)
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/accept4.h
create mode 100644 libc/src/sys/socket/accept4.h
create mode 100644 libc/src/sys/socket/linux/accept4.cpp
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/accept4.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/accept4.h
new file mode 100644
index 0000000000000..ebe82f189af50
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/accept4.h
@@ -0,0 +1,49 @@
+//===-- Implementation header for accept4 -----------------------*- 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_OSUTIL_SYSCALL_WRAPPERS_ACCEPT4_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_ACCEPT4_H
+
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
+#include <linux/net.h> // For SYS_ACCEPT4 socketcall number.
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> accept4(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen, int flags) {
+#ifdef SYS_accept4
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_accept4, sockfd, addr,
+ addrlen, flags);
+#elif defined(SYS_socketcall)
+ unsigned long sockcall_args[4] = {static_cast<unsigned long>(sockfd),
+ reinterpret_cast<unsigned long>(addr),
+ reinterpret_cast<unsigned long>(addrlen),
+ static_cast<unsigned long>(flags)};
+ int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_socketcall, SYS_ACCEPT4,
+ sockcall_args);
+#else
+#error "accept4 and socketcall syscalls unavailable for this platform."
+#endif
+
+ if (ret < 0)
+ return Error(-static_cast<int>(ret));
+ return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_ACCEPT4_H
diff --git a/libc/src/sys/socket/accept4.h b/libc/src/sys/socket/accept4.h
new file mode 100644
index 0000000000000..d5d14b684bb2e
--- /dev/null
+++ b/libc/src/sys/socket/accept4.h
@@ -0,0 +1,24 @@
+//===-- Implementation header for accept4 -----------------------*- 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_SYS_SOCKET_ACCEPT4_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT4_H
+
+#include "src/__support/macros/config.h"
+
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int accept4(int sockfd, struct sockaddr *__restrict addr,
+ socklen_t *__restrict addrlen, int flags);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_ACCEPT4_H
diff --git a/libc/src/sys/socket/linux/accept4.cpp b/libc/src/sys/socket/linux/accept4.cpp
new file mode 100644
index 0000000000000..bfe36c547072f
--- /dev/null
+++ b/libc/src/sys/socket/linux/accept4.cpp
@@ -0,0 +1,31 @@
+//===-- Linux implementation of accept4 -----------------------------------===//
+//
+// 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/sys/socket/accept4.h"
+
+#include "hdr/types/socklen_t.h"
+#include "hdr/types/struct_sockaddr.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/accept4.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, accept4,
+ (int sockfd, struct sockaddr *__restrict addr,
+ socklen_t *__restrict addrlen, int flags)) {
+ auto result = linux_syscalls::accept4(sockfd, addr, addrlen, flags);
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+
+ return result.value();
+}
+
+} // namespace LIBC_NAMESPACE_DECL
More information about the libc-commits
mailing list