[libc-commits] [libc] 02a543d - [libc] Add a simple implementation of the posix_spawn function.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Thu Oct 13 11:47:59 PDT 2022
Author: Siva Chandra Reddy
Date: 2022-10-13T18:47:47Z
New Revision: 02a543db66518b93b126feed43080feca0b14bd2
URL: https://github.com/llvm/llvm-project/commit/02a543db66518b93b126feed43080feca0b14bd2
DIFF: https://github.com/llvm/llvm-project/commit/02a543db66518b93b126feed43080feca0b14bd2.diff
LOG: [libc] Add a simple implementation of the posix_spawn function.
The implementation currently ignores all spawn attributes. Support for
them will be added in future changes.
A simple allocator for integration tests has been added so that the
integration test for posix_spawn can use the
posix_spawn_file_actions_add* functions.
Reviewed By: michaelrj
Differential Revision: https://reviews.llvm.org/D135752
Added:
libc/include/llvm-libc-types/posix_spawnattr_t.h
libc/src/spawn/linux/CMakeLists.txt
libc/src/spawn/linux/posix_spawn.cpp
libc/src/spawn/posix_spawn.h
libc/test/integration/src/spawn/CMakeLists.txt
libc/test/integration/src/spawn/posix_spawn_test.cpp
libc/test/integration/src/spawn/posix_spawn_test_binary.cpp
libc/test/integration/src/spawn/test_binary_properties.h
libc/test/integration/src/spawn/testdata/CMakeLists.txt
libc/utils/IntegrationTest/test.cpp
Modified:
libc/cmake/modules/LLVMLibCTestRules.cmake
libc/config/linux/api.td
libc/config/linux/x86_64/entrypoints.txt
libc/include/CMakeLists.txt
libc/include/llvm-libc-types/CMakeLists.txt
libc/spec/posix.td
libc/spec/spec.td
libc/src/spawn/CMakeLists.txt
libc/test/integration/src/CMakeLists.txt
libc/utils/IntegrationTest/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index f4f0a70a51b65..131bbad7c9c64 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -432,7 +432,8 @@ function(add_integration_test test_name)
libc.src.__support.threads.thread
libc.src.stdlib.atexit
libc.src.stdlib.exit
- libc.src.unistd.environ)
+ libc.src.unistd.environ
+ libc.utils.IntegrationTest.test)
list(REMOVE_DUPLICATES fq_deps_list)
# We don't want memory functions to be dependencies on integration tests.
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index fff1ff0c6211d..1aa1b3ff2cedd 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -291,5 +291,5 @@ def SysUtsNameAPI : PublicAPI<"sys/utsname.h"> {
}
def SpawnAPI : PublicAPI<"spawn.h"> {
- let Types = ["mode_t", "posix_spawn_file_actions_t"];
+ let Types = ["mode_t", "pid_t", "posix_spawnattr_t", "posix_spawn_file_actions_t"];
}
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 2855096ebe674..3a7b142a70f07 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -391,6 +391,7 @@ if(LLVM_LIBC_FULL_BUILD)
libc.src.signal.signal
# spawn.h entrypoints
+ libc.src.spawn.posix_spawn
libc.src.spawn.posix_spawn_file_actions_addclose
libc.src.spawn.posix_spawn_file_actions_adddup2
libc.src.spawn.posix_spawn_file_actions_addopen
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 35e84b7ec97ea..1e401a0a5efd3 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -220,6 +220,8 @@ add_gen_header(
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.mode_t
+ .llvm-libc-types.pid_t
+ .llvm-libc-types.posix_spawnattr_t
.llvm-libc-types.posix_spawn_file_actions_t
)
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 46b7393fea642..225f2fda8c52b 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -40,6 +40,7 @@ add_header(off_t HDR off_t.h)
add_header(once_flag HDR once_flag.h DEPENDS .__futex_word)
add_header(pid_t HDR pid_t.h)
add_header(posix_spawn_file_actions_t HDR posix_spawn_file_actions_t.h)
+add_header(posix_spawnattr_t HDR posix_spawnattr_t.h)
add_header(pthread_attr_t HDR pthread_attr_t.h DEPENDS .size_t)
add_header(pthread_key_t HDR pthread_key_t.h)
add_header(pthread_mutex_t HDR pthread_mutex_t.h DEPENDS .__futex_word .__mutex_type)
diff --git a/libc/include/llvm-libc-types/posix_spawnattr_t.h b/libc/include/llvm-libc-types/posix_spawnattr_t.h
new file mode 100644
index 0000000000000..f1bcb3e1434f8
--- /dev/null
+++ b/libc/include/llvm-libc-types/posix_spawnattr_t.h
@@ -0,0 +1,16 @@
+//===-- Definition of type posix_spawn_file_actions_t ---------------------===//
+//
+// 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_TYPES_POSIX_SPAWNATTR_T_H
+#define __LLVM_LIBC_TYPES_POSIX_SPAWNATTR_T_H
+
+typedef struct {
+ // This data structure will be populated as required.
+} posix_spawnattr_t;
+
+#endif // __LLVM_LIBC_TYPES_POSIX_SPAWNATTR_T_H
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index 431a57108ac89..53906d0d060e9 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -52,8 +52,12 @@ def AtForkCallbackT : NamedType<"__atfork_callback_t">;
def PosixSpawnFileActionsT : NamedType<"posix_spawn_file_actions_t">;
def PosixSpawnFileActionsTPtr : PtrType<PosixSpawnFileActionsT>;
+def ConstPosixSpawnFileActionsTPtr : ConstType<PosixSpawnFileActionsTPtr>;
def PosixSpawnFileActionsTRestrictedPtr : RestrictedPtrType<PosixSpawnFileActionsT>;
+def PosixSpawnAttrT : NamedType<"posix_spawnattr_t">;
+def RestrictedPosixSpawnAttrTPtrType : RestrictedPtrType<PosixSpawnAttrT>;
+
def POSIX : StandardSpec<"POSIX"> {
PtrType CharPtr = PtrType<CharType>;
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
@@ -1052,7 +1056,7 @@ def POSIX : StandardSpec<"POSIX"> {
HeaderSpec Spawn = HeaderSpec<
"spawn.h",
[], // Macros
- [PosixSpawnFileActionsT, ModeTType],
+ [ModeTType, PosixSpawnAttrT, PidT, PosixSpawnFileActionsT],
[], // Enumerations
[
FunctionSpec<
@@ -1081,6 +1085,13 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<IntType>,
[ArgSpec<PosixSpawnFileActionsTPtr>]
>,
+ FunctionSpec<
+ "posix_spawn",
+ RetValSpec<IntType>,
+ [ArgSpec<RestrictedPidTPtr>, ArgSpec<ConstCharRestrictedPtr>,
+ ArgSpec<PosixSpawnFileActionsTPtr>, ArgSpec<RestrictedPosixSpawnAttrTPtrType>,
+ ArgSpec<ConstCharRestrictedPtrPtr>, ArgSpec<ConstCharRestrictedPtrPtr>]
+ >,
]
>;
diff --git a/libc/spec/spec.td b/libc/spec/spec.td
index 85a8f46eb59db..1c39bbaa17b9f 100644
--- a/libc/spec/spec.td
+++ b/libc/spec/spec.td
@@ -80,6 +80,7 @@ def ConstCharPtr : ConstType<CharPtr>;
def CharRestrictedPtr : RestrictedPtrType<CharType>;
def CharRestrictedPtrPtr : RestrictedPtrType<CharPtr>;
def ConstCharRestrictedPtr : ConstType<CharRestrictedPtr>;
+def ConstCharRestrictedPtrPtr : PtrType<ConstCharRestrictedPtr>;
def OnceFlagType : NamedType<"once_flag">;
def OnceFlagTypePtr : PtrType<OnceFlagType>;
@@ -115,6 +116,8 @@ def FILERestrictedPtr : RestrictedPtrType<FILE>;
def PThreadTType : NamedType<"pthread_t">;
def PidT : NamedType<"pid_t">;
+def RestrictedPidTPtr : RestrictedPtrType<PidT>;
+
def StructRUsage : NamedType<"struct rusage">;
def StructRUsagePtr : PtrType<StructRUsage>;
diff --git a/libc/src/spawn/CMakeLists.txt b/libc/src/spawn/CMakeLists.txt
index 95a0c7436d263..fd929fa0cee16 100644
--- a/libc/src/spawn/CMakeLists.txt
+++ b/libc/src/spawn/CMakeLists.txt
@@ -1,3 +1,7 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
add_header_library(
file_actions
HDRS
@@ -63,3 +67,10 @@ add_entrypoint_object(
libc.include.errno
libc.include.spawn
)
+
+add_entrypoint_object(
+ posix_spawn
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.posix_spawn
+)
diff --git a/libc/src/spawn/linux/CMakeLists.txt b/libc/src/spawn/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..9bd3ac50415b1
--- /dev/null
+++ b/libc/src/spawn/linux/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_entrypoint_object(
+ posix_spawn
+ SRCS
+ posix_spawn.cpp
+ HDRS
+ ../posix_spawn.h
+ DEPENDS
+ libc.include.fcntl
+ libc.include.spawn
+ libc.include.sys_syscall
+ libc.src.__support.CPP.optional
+ libc.src.__support.OSUtil.osutil
+ libc.src.spawn.file_actions
+)
diff --git a/libc/src/spawn/linux/posix_spawn.cpp b/libc/src/spawn/linux/posix_spawn.cpp
new file mode 100644
index 0000000000000..2f8287238ec86
--- /dev/null
+++ b/libc/src/spawn/linux/posix_spawn.cpp
@@ -0,0 +1,139 @@
+//===-- Linux implementation of posix_spawn -------------------------------===//
+//
+// 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/spawn/posix_spawn.h"
+
+#include "src/__support/CPP/optional.h"
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+#include "src/spawn/file_actions.h"
+
+#include <fcntl.h>
+#include <spawn.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+namespace {
+
+pid_t fork() {
+ // TODO: Use only the clone syscall and use a sperate small stack in the child
+ // to avoid duplicating the complete stack from the parent. A new stack will
+ // be created on exec anyway so duplicating the full stack is unnecessary.
+#ifdef SYS_fork
+ return __llvm_libc::syscall_impl(SYS_fork);
+#elif defined(SYS_clone)
+ return __llvm_libc::syscall_impl(SYS_clone, SIGCHLD, 0);
+#else
+#error "SYS_fork or SYS_clone not available."
+#endif
+}
+
+cpp::optional<int> open(const char *path, int oflags, mode_t mode) {
+#ifdef SYS_open
+ int fd = __llvm_libc::syscall_impl(SYS_open, path, oflags, mode);
+#else
+ int fd = __llvm_libc::syscall_impl(SYS_openat, AT_FDCWD, path, oflags, mode);
+#endif
+ if (fd > 0)
+ return fd;
+ // The open function is called as part of the child process' preparatory
+ // steps. If an open fails, the child process just exits. So, unlike
+ // the public open function, we do not need to set errno here.
+ return cpp::nullopt;
+}
+
+void close(int fd) { __llvm_libc::syscall_impl(SYS_close, fd); }
+
+bool dup2(int fd, int newfd) {
+ long ret = __llvm_libc::syscall_impl(SYS_dup2, fd, newfd);
+ return ret < 0 ? false : true;
+}
+
+// All exits from child_process are error exits. So, we use a simple
+// exit implementation which exits with code 127.
+void exit() {
+ for (;;) {
+ __llvm_libc::syscall_impl(SYS_exit_group, 127);
+ __llvm_libc::syscall_impl(SYS_exit, 127);
+ }
+}
+
+void child_process(const char *__restrict path,
+ const posix_spawn_file_actions_t *file_actions,
+ const posix_spawnattr_t *__restrict, // For now unused
+ char *const *__restrict argv, char *const *__restrict envp) {
+ // TODO: In the code below, the child_process just exits on error during
+ // processing |file_actions| and |attr|. The correct way would be to exit
+ // after conveying the information about the failure to the parent process
+ // (via a pipe for example).
+ // TODO: Handle |attr|.
+
+ if (file_actions != nullptr) {
+ auto *act = reinterpret_cast<BaseSpawnFileAction *>(file_actions->__front);
+ while (act != nullptr) {
+ switch (act->type) {
+ case BaseSpawnFileAction::OPEN: {
+ auto *open_act = reinterpret_cast<SpawnFileOpenAction *>(act);
+ auto fd = open(open_act->path, open_act->oflag, open_act->mode);
+ if (!fd)
+ exit();
+ int actual_fd = *fd;
+ if (actual_fd != open_act->fd) {
+ bool dup2_result = dup2(actual_fd, open_act->fd);
+ close(actual_fd); // The old fd is not needed anymore.
+ if (!dup2_result)
+ exit();
+ }
+ break;
+ }
+ case BaseSpawnFileAction::CLOSE: {
+ auto *close_act = reinterpret_cast<SpawnFileCloseAction *>(act);
+ close(close_act->fd);
+ break;
+ }
+ case BaseSpawnFileAction::DUP2: {
+ auto *dup2_act = reinterpret_cast<SpawnFileDup2Action *>(act);
+ if (!dup2(dup2_act->fd, dup2_act->newfd))
+ exit();
+ break;
+ }
+ }
+ act = act->next;
+ }
+ }
+
+ if (__llvm_libc::syscall_impl(SYS_execve, path, argv, envp) < 0)
+ exit();
+}
+
+} // anonymous namespace
+
+LLVM_LIBC_FUNCTION(int, posix_spawn,
+ (pid_t *__restrict pid, const char *__restrict path,
+ const posix_spawn_file_actions_t *file_actions,
+ const posix_spawnattr_t *__restrict attr,
+ char *const *__restrict argv,
+ char *const *__restrict envp)) {
+ pid_t cpid = fork();
+ if (cpid == 0)
+ child_process(path, file_actions, attr, argv, envp);
+ else if (cpid < 0)
+ return -cpid;
+
+ if (pid != nullptr)
+ *pid = cpid;
+
+ // TODO: Before returning, one should wait for the child_process to startup
+ // successfully. For now, we will just return. Future changes will add proper
+ // wait (using pipes for example).
+
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/spawn/posix_spawn.h b/libc/src/spawn/posix_spawn.h
new file mode 100644
index 0000000000000..721462701b25f
--- /dev/null
+++ b/libc/src/spawn/posix_spawn.h
@@ -0,0 +1,23 @@
+//===-- Implementation header for posix_spawn -------------------*- 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_SPAWN_POSIX_SPAWN_H
+#define LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_H
+
+#include <spawn.h>
+
+namespace __llvm_libc {
+
+int posix_spawn(pid_t *__restrict pid, const char *__restrict path,
+ const posix_spawn_file_actions_t *file_actions,
+ const posix_spawnattr_t *__restrict attr,
+ char *const *__restrict argv, char *const *__restrict envp);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SPAWN_POSIX_SPAWN_H
diff --git a/libc/test/integration/src/CMakeLists.txt b/libc/test/integration/src/CMakeLists.txt
index c86cd178a3ce6..1104b3de99e9b 100644
--- a/libc/test/integration/src/CMakeLists.txt
+++ b/libc/test/integration/src/CMakeLists.txt
@@ -1,5 +1,6 @@
add_subdirectory(__support)
add_subdirectory(pthread)
+add_subdirectory(spawn)
add_subdirectory(stdio)
add_subdirectory(stdlib)
add_subdirectory(threads)
diff --git a/libc/test/integration/src/spawn/CMakeLists.txt b/libc/test/integration/src/spawn/CMakeLists.txt
new file mode 100644
index 0000000000000..dd0e8a383d7b6
--- /dev/null
+++ b/libc/test/integration/src/spawn/CMakeLists.txt
@@ -0,0 +1,46 @@
+add_custom_target(spawn-integration-tests)
+add_dependencies(libc-integration-tests spawn-integration-tests)
+
+add_executable(
+ libc_posix_spawn_test_binary
+ EXCLUDE_FROM_ALL
+ posix_spawn_test_binary.cpp
+ test_binary_properties.h
+)
+set_target_properties(
+ libc_posix_spawn_test_binary
+ PROPERTIES
+ OUTPUT_NAME libc_posix_spawn_test_binary
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+add_header_library(
+ test_binary_properties
+ HDRS
+ test_binary_properties.h
+)
+
+add_integration_test(
+ posix_spawn_test
+ SUITE
+ spawn-integration-tests
+ SRCS
+ posix_spawn_test.cpp
+ LOADER
+ libc.loader.linux.crt1
+ DEPENDS
+ libc_posix_spawn_test_binary
+ libc.test.integration.src.spawn.test_binary_properties
+ libc.include.fcntl
+ libc.include.signal
+ libc.include.spawn
+ libc.include.sys_wait
+ libc.src.signal.raise
+ libc.src.spawn.posix_spawn
+ libc.src.spawn.posix_spawn_file_actions_addopen
+ libc.src.spawn.posix_spawn_file_actions_destroy
+ libc.src.spawn.posix_spawn_file_actions_init
+ libc.src.sys.wait.waitpid
+)
+
+add_subdirectory(testdata)
diff --git a/libc/test/integration/src/spawn/posix_spawn_test.cpp b/libc/test/integration/src/spawn/posix_spawn_test.cpp
new file mode 100644
index 0000000000000..74fb7d339a2f4
--- /dev/null
+++ b/libc/test/integration/src/spawn/posix_spawn_test.cpp
@@ -0,0 +1,51 @@
+//===-- Unittests for posix_spawn -----------------------------------------===//
+//
+// 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 "test_binary_properties.h"
+
+#include "src/spawn/posix_spawn.h"
+#include "src/spawn/posix_spawn_file_actions_addopen.h"
+#include "src/spawn/posix_spawn_file_actions_destroy.h"
+#include "src/spawn/posix_spawn_file_actions_init.h"
+#include "src/sys/wait/waitpid.h"
+#include "utils/IntegrationTest/test.h"
+
+#include <fcntl.h>
+#include <spawn.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/wait.h>
+
+char arg0[] = "libc_posix_spawn_test_binary";
+char *argv[] = {
+ arg0,
+ nullptr,
+};
+
+void spawn_and_wait_for_normal_exit(char **envp) {
+ pid_t cpid;
+ posix_spawn_file_actions_t file_actions;
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_init(&file_actions), 0);
+ __llvm_libc::posix_spawn_file_actions_addopen(
+ &file_actions, CHILD_FD, "testdata/posix_spawn.test", O_RDONLY, 0);
+ ASSERT_EQ(
+ __llvm_libc::posix_spawn(&cpid, arg0, &file_actions, nullptr, argv, envp),
+ 0);
+ ASSERT_TRUE(cpid > 0);
+ int status;
+ ASSERT_EQ(__llvm_libc::waitpid(cpid, &status, 0), cpid);
+ ASSERT_EQ(__llvm_libc::posix_spawn_file_actions_destroy(&file_actions), 0);
+ ASSERT_TRUE(WIFEXITED(status));
+ int exit_status = WEXITSTATUS(status);
+ ASSERT_EQ(exit_status, 0);
+}
+
+TEST_MAIN(int argc, char **argv, char **envp) {
+ spawn_and_wait_for_normal_exit(envp);
+ return 0;
+}
diff --git a/libc/test/integration/src/spawn/posix_spawn_test_binary.cpp b/libc/test/integration/src/spawn/posix_spawn_test_binary.cpp
new file mode 100644
index 0000000000000..7aec39c192928
--- /dev/null
+++ b/libc/test/integration/src/spawn/posix_spawn_test_binary.cpp
@@ -0,0 +1,22 @@
+#include "test_binary_properties.h"
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+ if (argc != 1)
+ return 5;
+ constexpr size_t bufsize = sizeof(TEXT);
+ char buf[bufsize];
+ ssize_t readsize = bufsize - 1;
+ ssize_t len = read(CHILD_FD, buf, readsize);
+ if (len != readsize) {
+ return 1;
+ }
+ buf[readsize] = '\0'; // Null terminator
+ if (close(CHILD_FD) != 0)
+ return 2;
+ if (strcmp(buf, TEXT) != 0)
+ return 3;
+ return 0;
+}
diff --git a/libc/test/integration/src/spawn/test_binary_properties.h b/libc/test/integration/src/spawn/test_binary_properties.h
new file mode 100644
index 0000000000000..f1521c218c0cb
--- /dev/null
+++ b/libc/test/integration/src/spawn/test_binary_properties.h
@@ -0,0 +1,15 @@
+//===-- Common definitions shared between test binary and test --*- 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 LIBC_TEST_INTEGRATION_SRC_SPAWN_TEST_BINARY_PROPERTIES_H
+#define LIBC_TEST_INTEGRATION_SRC_SPAWN_TEST_BINARY_PROPERTIES_H
+
+constexpr int CHILD_FD = 10;
+constexpr char TEXT[] = "Hello, posix_spawn";
+
+#endif // LIBC_TEST_INTEGRATION_SRC_SPAWN_TEST_BINARY_PROPERTIES_H
diff --git a/libc/test/integration/src/spawn/testdata/CMakeLists.txt b/libc/test/integration/src/spawn/testdata/CMakeLists.txt
new file mode 100644
index 0000000000000..f6da5dc792c42
--- /dev/null
+++ b/libc/test/integration/src/spawn/testdata/CMakeLists.txt
@@ -0,0 +1 @@
+file(GENERATE OUTPUT posix_spawn.test CONTENT "Hello, posix_spawn")
diff --git a/libc/utils/IntegrationTest/CMakeLists.txt b/libc/utils/IntegrationTest/CMakeLists.txt
index 3866bbe929c7d..3d8a3497bbb2f 100644
--- a/libc/utils/IntegrationTest/CMakeLists.txt
+++ b/libc/utils/IntegrationTest/CMakeLists.txt
@@ -1,5 +1,7 @@
-add_header_library(
+add_object_library(
test
+ SRCS
+ test.cpp
HDRS
test.h
DEPENDS
diff --git a/libc/utils/IntegrationTest/test.cpp b/libc/utils/IntegrationTest/test.cpp
new file mode 100644
index 0000000000000..3de4fa7525cc3
--- /dev/null
+++ b/libc/utils/IntegrationTest/test.cpp
@@ -0,0 +1,32 @@
+//===-- Simple malloc and free for use with integration tests -------------===//
+//
+// 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 <stddef.h>
+#include <stdint.h>
+
+// Integration tests cannot use the SCUDO standalone allocator as SCUDO pulls
+// various other parts of the libc. Since SCUDO development does not use
+// LLVM libc build rules, it is very hard to keep track or pull all that SCUDO
+// requires. Hence, as a work around for this problem, we use a simple allocator
+// which just hands out continuous blocks from a statically allocated chunk of
+// memory.
+
+static uint8_t memory[16384];
+static uint8_t *ptr = memory;
+
+extern "C" {
+
+void *malloc(size_t s) {
+ void *mem = ptr;
+ ptr += s;
+ return mem;
+}
+
+void free(void *) {}
+
+} // extern "C"
More information about the libc-commits
mailing list