[libc-commits] [libc] [libc] Implement lockf in unistd (#230856) (PR #231145)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Wed Oct 14 00:15:00 PDT 2026


================
@@ -0,0 +1,75 @@
+//===-- Integration test for lockf ----------------------------------------===//
+//
+// 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 "hdr/errno_macros.h"
+#include "hdr/fcntl_macros.h"
+#include "hdr/sys_stat_macros.h"
+#include "hdr/sys_wait_macros.h"
+#include "hdr/unistd_macros.h"
+#include "src/fcntl/open.h"
+#include "src/stdlib/exit.h"
+#include "src/sys/wait/waitpid.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+#include "src/unistd/lockf.h"
+#include "src/unistd/unlink.h"
+
+#include "test/IntegrationTest/test.h"
+
+#include <errno.h>
+
+TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
+          [[maybe_unused]] char **envp) {
+  constexpr const char TEST_FILE[] = "lockf_integration.test";
+
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
+  ASSERT_TRUE(fd > 0);
+
+  // Acquire an exclusive lock on the file in the parent process.
+  ASSERT_EQ(LIBC_NAMESPACE::lockf(fd, F_LOCK, 0), 0);
+
+  pid_t pid = LIBC_NAMESPACE::fork();
+  ASSERT_TRUE(pid >= 0);
+
+  if (pid == 0) {
+    // Child process:
+    int child_fd = LIBC_NAMESPACE::open(TEST_FILE, O_RDWR, 0);
+    if (child_fd < 0)
+      LIBC_NAMESPACE::exit(1);
+
+    // F_TEST should fail because the section is locked by another process
+    // (parent).
+    if (LIBC_NAMESPACE::lockf(child_fd, F_TEST, 0) == 0)
+      LIBC_NAMESPACE::exit(2);
+    if (errno != EACCES && errno != EAGAIN)
+      LIBC_NAMESPACE::exit(3);
+
+    // F_TLOCK should fail because non-blocking lock cannot be acquired.
+    if (LIBC_NAMESPACE::lockf(child_fd, F_TLOCK, 0) == 0)
+      LIBC_NAMESPACE::exit(4);
+    if (errno != EACCES && errno != EAGAIN)
+      LIBC_NAMESPACE::exit(5);
+
+    LIBC_NAMESPACE::close(child_fd);
+    LIBC_NAMESPACE::exit(0);
+  }
+
+  // Parent process waits for child.
+  int status = 0;
+  pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);
+  ASSERT_EQ(cpid, pid);
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(WEXITSTATUS(status), 0);
+
+  // Release lock and clean up file.
+  ASSERT_EQ(LIBC_NAMESPACE::lockf(fd, F_ULOCK, 0), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::close(fd), 0);
+  ASSERT_EQ(LIBC_NAMESPACE::unlink(TEST_FILE), 0);
----------------
labath wrote:

Use scope_exit here (you can skip unlocking, that will be handled automatically by close)

https://github.com/llvm/llvm-project/pull/231145


More information about the libc-commits mailing list