gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/eventfd.cc (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <errno.h>
    16  #include <pthread.h>
    17  #include <stdio.h>
    18  #include <stdlib.h>
    19  #include <string.h>
    20  #include <sys/epoll.h>
    21  #include <sys/stat.h>
    22  #include <sys/types.h>
    23  #include <unistd.h>
    24  
    25  #include "gtest/gtest.h"
    26  #include "test/util/epoll_util.h"
    27  #include "test/util/eventfd_util.h"
    28  #include "test/util/test_util.h"
    29  #include "test/util/thread_util.h"
    30  
    31  namespace gvisor {
    32  namespace testing {
    33  
    34  namespace {
    35  
    36  TEST(EventfdTest, Nonblock) {
    37    FileDescriptor efd =
    38        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE));
    39  
    40    uint64_t l;
    41    ASSERT_THAT(read(efd.get(), &l, sizeof(l)), SyscallFailsWithErrno(EAGAIN));
    42  
    43    l = 1;
    44    ASSERT_THAT(write(efd.get(), &l, sizeof(l)), SyscallSucceeds());
    45  
    46    l = 0;
    47    ASSERT_THAT(read(efd.get(), &l, sizeof(l)), SyscallSucceeds());
    48    EXPECT_EQ(l, 1);
    49  
    50    ASSERT_THAT(read(efd.get(), &l, sizeof(l)), SyscallFailsWithErrno(EAGAIN));
    51  }
    52  
    53  void* read_three_times(void* arg) {
    54    int efd = *reinterpret_cast<int*>(arg);
    55    uint64_t l;
    56    EXPECT_THAT(read(efd, &l, sizeof(l)), SyscallSucceedsWithValue(sizeof(l)));
    57    EXPECT_THAT(read(efd, &l, sizeof(l)), SyscallSucceedsWithValue(sizeof(l)));
    58    EXPECT_THAT(read(efd, &l, sizeof(l)), SyscallSucceedsWithValue(sizeof(l)));
    59    return nullptr;
    60  }
    61  
    62  TEST(EventfdTest, BlockingWrite) {
    63    FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_SEMAPHORE));
    64    int efd = fd.get();
    65  
    66    pthread_t p;
    67    ASSERT_THAT(pthread_create(&p, nullptr, read_three_times,
    68                               reinterpret_cast<void*>(&efd)),
    69                SyscallSucceeds());
    70  
    71    uint64_t l = 1;
    72    ASSERT_THAT(write(efd, &l, sizeof(l)), SyscallSucceeds());
    73    EXPECT_EQ(l, 1);
    74  
    75    ASSERT_THAT(write(efd, &l, sizeof(l)), SyscallSucceeds());
    76    EXPECT_EQ(l, 1);
    77  
    78    ASSERT_THAT(write(efd, &l, sizeof(l)), SyscallSucceeds());
    79    EXPECT_EQ(l, 1);
    80  
    81    ASSERT_THAT(pthread_join(p, nullptr), SyscallSucceeds());
    82  }
    83  
    84  TEST(EventfdTest, SmallWrite) {
    85    FileDescriptor efd =
    86        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE));
    87  
    88    uint64_t l = 16;
    89    ASSERT_THAT(write(efd.get(), &l, 4), SyscallFailsWithErrno(EINVAL));
    90  }
    91  
    92  TEST(EventfdTest, SmallRead) {
    93    FileDescriptor efd =
    94        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE));
    95  
    96    uint64_t l = 1;
    97    ASSERT_THAT(write(efd.get(), &l, sizeof(l)), SyscallSucceeds());
    98  
    99    l = 0;
   100    ASSERT_THAT(read(efd.get(), &l, 4), SyscallFailsWithErrno(EINVAL));
   101  }
   102  
   103  TEST(EventfdTest, IllegalSeek) {
   104    // TODO: b/298787679 - this test fails on 6.0+ kernels.
   105    SKIP_IF(!IsRunningOnGvisor());
   106  
   107    FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0));
   108    EXPECT_THAT(lseek(efd.get(), 0, SEEK_SET), SyscallFailsWithErrno(ESPIPE));
   109  }
   110  
   111  TEST(EventfdTest, IllegalPread) {
   112    FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0));
   113    int l;
   114    EXPECT_THAT(pread(efd.get(), &l, sizeof(l), 0),
   115                SyscallFailsWithErrno(ESPIPE));
   116  }
   117  
   118  TEST(EventfdTest, IllegalPwrite) {
   119    FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, 0));
   120    EXPECT_THAT(pwrite(efd.get(), "x", 1, 0), SyscallFailsWithErrno(ESPIPE));
   121  }
   122  
   123  TEST(EventfdTest, BigWrite) {
   124    FileDescriptor efd =
   125        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE));
   126  
   127    uint64_t big[16];
   128    big[0] = 16;
   129    ASSERT_THAT(write(efd.get(), big, sizeof(big)), SyscallSucceeds());
   130  }
   131  
   132  TEST(EventfdTest, BigRead) {
   133    FileDescriptor efd =
   134        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE));
   135  
   136    uint64_t l = 1;
   137    ASSERT_THAT(write(efd.get(), &l, sizeof(l)), SyscallSucceeds());
   138  
   139    uint64_t big[16];
   140    ASSERT_THAT(read(efd.get(), big, sizeof(big)), SyscallSucceeds());
   141    EXPECT_EQ(big[0], 1);
   142  }
   143  
   144  TEST(EventfdTest, BigWriteBigRead) {
   145    FileDescriptor efd =
   146        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(0, EFD_NONBLOCK | EFD_SEMAPHORE));
   147  
   148    uint64_t l[16];
   149    l[0] = 16;
   150    ASSERT_THAT(write(efd.get(), l, sizeof(l)), SyscallSucceeds());
   151    ASSERT_THAT(read(efd.get(), l, sizeof(l)), SyscallSucceeds());
   152    EXPECT_EQ(l[0], 1);
   153  }
   154  
   155  TEST(EventfdTest, NotifyNonZero) {
   156    // Waits will time out at 10 seconds.
   157    constexpr int kEpollTimeoutMs = 10000;
   158    // Create an eventfd descriptor.
   159    FileDescriptor efd =
   160        ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(7, EFD_NONBLOCK | EFD_SEMAPHORE));
   161    // Create an epoll fd to listen to efd.
   162    FileDescriptor epollfd = ASSERT_NO_ERRNO_AND_VALUE(NewEpollFD());
   163    // Add efd to epoll.
   164    ASSERT_NO_ERRNO(
   165        RegisterEpollFD(epollfd.get(), efd.get(), EPOLLIN | EPOLLET, efd.get()));
   166  
   167    // Use epoll to get a value from efd.
   168    struct epoll_event out_ev;
   169    int wait_out = epoll_wait(epollfd.get(), &out_ev, 1, kEpollTimeoutMs);
   170    EXPECT_EQ(wait_out, 1);
   171    EXPECT_EQ(efd.get(), out_ev.data.fd);
   172    uint64_t val = 0;
   173    ASSERT_THAT(read(efd.get(), &val, sizeof(val)), SyscallSucceeds());
   174    EXPECT_EQ(val, 1);
   175  
   176    // Start a thread that, after this thread blocks on epoll_wait, will write to
   177    // efd. This is racy -- it's possible that this write will happen after
   178    // epoll_wait times out.
   179    ScopedThread t([&efd] {
   180      sleep(5);
   181      uint64_t val = 1;
   182      EXPECT_THAT(write(efd.get(), &val, sizeof(val)),
   183                  SyscallSucceedsWithValue(sizeof(val)));
   184    });
   185  
   186    // epoll_wait should return once the thread writes.
   187    wait_out = epoll_wait(epollfd.get(), &out_ev, 1, kEpollTimeoutMs);
   188    EXPECT_EQ(wait_out, 1);
   189    EXPECT_EQ(efd.get(), out_ev.data.fd);
   190  
   191    val = 0;
   192    ASSERT_THAT(read(efd.get(), &val, sizeof(val)), SyscallSucceeds());
   193    EXPECT_EQ(val, 1);
   194  }
   195  
   196  TEST(EventfdTest, SpliceReturnsEINVAL) {
   197    // Splicing into eventfd has been disabled in
   198    // 36e2c7421f02 ("fs: don't allow splice read/write without explicit ops").
   199    SKIP_IF(!IsRunningOnGvisor());
   200  
   201    // Create an eventfd descriptor.
   202    FileDescriptor efd = ASSERT_NO_ERRNO_AND_VALUE(NewEventFD(7, 0));
   203  
   204    // Create a new pipe.
   205    int fds[2];
   206    ASSERT_THAT(pipe(fds), SyscallSucceeds());
   207    const FileDescriptor rfd(fds[0]);
   208    const FileDescriptor wfd(fds[1]);
   209  
   210    // Fill the pipe.
   211    std::vector<char> buf(kPageSize);
   212    ASSERT_THAT(write(wfd.get(), buf.data(), buf.size()),
   213                SyscallSucceedsWithValue(kPageSize));
   214  
   215    EXPECT_THAT(splice(rfd.get(), nullptr, efd.get(), nullptr, kPageSize, 0),
   216                SyscallFailsWithErrno(EINVAL));
   217  }
   218  
   219  }  // namespace
   220  
   221  }  // namespace testing
   222  }  // namespace gvisor