Skip to content

[libc][fcntl] Simplify the handling of the return value from syscall … #96325

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 26, 2024

Conversation

simonzgx
Copy link
Contributor

@simonzgx simonzgx commented Jun 21, 2024

Fixes #95570

@llvmbot llvmbot added the libc label Jun 21, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 21, 2024

@llvm/pr-subscribers-libc

Author: Xu Zhang (simonzgx)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/96325.diff

3 Files Affected:

  • (modified) libc/src/__support/OSUtil/linux/fcntl.cpp (+3-7)
  • (modified) libc/test/src/fcntl/CMakeLists.txt (+1)
  • (modified) libc/test/src/fcntl/fcntl_test.cpp (+20)
diff --git a/libc/src/__support/OSUtil/linux/fcntl.cpp b/libc/src/__support/OSUtil/linux/fcntl.cpp
index b087f898c395d..083deb8c33681 100644
--- a/libc/src/__support/OSUtil/linux/fcntl.cpp
+++ b/libc/src/__support/OSUtil/linux/fcntl.cpp
@@ -67,15 +67,11 @@ int fcntl(int fd, int cmd, void *arg) {
   }
   case F_GETOWN: {
     struct f_owner_ex fex;
-    int retVal =
+    int ret =
         LIBC_NAMESPACE::syscall_impl<int>(SYS_fcntl, fd, F_GETOWN_EX, &fex);
-    if (retVal == -EINVAL)
-      return LIBC_NAMESPACE::syscall_impl<int>(SYS_fcntl, fd, cmd,
-                                               reinterpret_cast<void *>(arg));
-    if (static_cast<unsigned long>(retVal) <= -4096UL)
+    if (ret >= 0)
       return fex.type == F_OWNER_PGRP ? -fex.pid : fex.pid;
-
-    libc_errno = -retVal;
+    libc_errno = -ret;
     return -1;
   }
   // The general case
diff --git a/libc/test/src/fcntl/CMakeLists.txt b/libc/test/src/fcntl/CMakeLists.txt
index aae296f074bea..48048b7fe8866 100644
--- a/libc/test/src/fcntl/CMakeLists.txt
+++ b/libc/test/src/fcntl/CMakeLists.txt
@@ -29,6 +29,7 @@ add_libc_unittest(
     libc.src.fcntl.fcntl
     libc.src.fcntl.open
     libc.src.unistd.close
+    libc.src.unistd.getpid
     libc.hdr.types.struct_flock
     libc.hdr.fcntl_macros
     libc.test.UnitTest.ErrnoSetterMatcher
diff --git a/libc/test/src/fcntl/fcntl_test.cpp b/libc/test/src/fcntl/fcntl_test.cpp
index fc909acc1aa0b..f50109322e6b2 100644
--- a/libc/test/src/fcntl/fcntl_test.cpp
+++ b/libc/test/src/fcntl/fcntl_test.cpp
@@ -12,9 +12,11 @@
 #include "src/fcntl/fcntl.h"
 #include "src/fcntl/open.h"
 #include "src/unistd/close.h"
+#include "src/unistd/getpid.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
 
+#include <fcntl.h>
 #include <stdio.h>
 #include <sys/stat.h> // For S_IRWXU
 
@@ -163,3 +165,21 @@ TEST(LlvmLibcFcntlTest, UseAfterClose) {
   ASSERT_EQ(-1, LIBC_NAMESPACE::fcntl(fd, F_GETFL));
   ASSERT_ERRNO_EQ(EBADF);
 }
+
+TEST(LlvmLibcFcntlTest, SetGetOwnerTest) {
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+  pid_t pid = LIBC_NAMESPACE::getpid();
+  ASSERT_GT(pid, -1);
+  constexpr const char *TEST_FILE_NAME = "testdata/fcntl_set_get_owner.test";
+  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
+  int ret = LIBC_NAMESPACE::fcntl(fd, F_SETOWN, pid);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(ret, -1);
+  int ret2 = LIBC_NAMESPACE::fcntl(fd, F_GETOWN);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_EQ(ret2, pid);
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+}

@simonzgx simonzgx force-pushed the fix-fcntl-F_GETOWN branch from 39cb715 to b25d759 Compare June 21, 2024 16:37
@simonzgx
Copy link
Contributor Author

I just fixed a UT failure. Please review it again and help merge if everything is OK.

@nickdesaulniers
Copy link
Member

Why was the unit test failing? Why would clearing errno fix it?

@@ -162,4 +163,23 @@ TEST(LlvmLibcFcntlTest, UseAfterClose) {
ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
ASSERT_EQ(-1, LIBC_NAMESPACE::fcntl(fd, F_GETFL));
ASSERT_ERRNO_EQ(EBADF);
LIBC_NAMESPACE::libc_errno = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
LIBC_NAMESPACE::libc_errno = 0;
// Clear errno for subsequent unit tests.
LIBC_NAMESPACE::libc_errno = 0;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed that other tests tend to zero libc_errno before running any operations. We should clear errno first, for tests that need it, rather than reset it after tests that touch it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, fixed. And I'm curious, is this just a matter of convention?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convention. I think UseAfterClose and the other unit tests that use ASSERT_ERRNO_ macros should be doing this, too.

@nickdesaulniers nickdesaulniers merged commit 7c4fc9c into llvm:main Jun 26, 2024
6 checks passed
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this pull request Jul 3, 2024
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc] Investigate if the current implementation of the fcntl is correct.
4 participants