gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/test/syscalls/linux/socket_stream_blocking.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 "test/syscalls/linux/socket_stream_blocking.h"
    16  
    17  #include <stdio.h>
    18  #include <sys/socket.h>
    19  #include <sys/types.h>
    20  #include <sys/un.h>
    21  
    22  #include "gtest/gtest.h"
    23  #include "absl/time/clock.h"
    24  #include "absl/time/time.h"
    25  #include "test/syscalls/linux/unix_domain_socket_test_util.h"
    26  #include "test/util/socket_util.h"
    27  #include "test/util/test_util.h"
    28  #include "test/util/thread_util.h"
    29  #include "test/util/timer_util.h"
    30  
    31  namespace gvisor {
    32  namespace testing {
    33  
    34  TEST_P(BlockingStreamSocketPairTest, BlockPartialWriteClosed) {
    35    // FIXME(b/35921550): gVisor doesn't support SO_SNDBUF on UDS, nor does it
    36    // enforce any limit; it will write arbitrary amounts of data without
    37    // blocking.
    38    SKIP_IF(IsRunningOnGvisor());
    39  
    40    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    41  
    42    // Set the send buffer size which will disable auto tuning and will block the
    43    // partial write while sending the data more than the send buffer size.
    44    constexpr int kSndBufSz = INT_MAX;
    45    ASSERT_THAT(setsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, &kSndBufSz,
    46                           sizeof(kSndBufSz)),
    47                SyscallSucceeds());
    48  
    49    int buffer_size;
    50    socklen_t length = sizeof(buffer_size);
    51    ASSERT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF,
    52                           &buffer_size, &length),
    53                SyscallSucceeds());
    54  
    55    int wfd = sockets->first_fd();
    56    ScopedThread t([wfd, buffer_size]() {
    57      std::vector<char> buf(2 * buffer_size);
    58      // Write more than fits in the buffer. Blocks then returns partial write
    59      // when the other end is closed. The next call returns EPIPE.
    60      //
    61      // N.B. writes occur in chunks, so we may see less than buffer_size from
    62      // the first call.
    63      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
    64                  SyscallSucceedsWithValue(::testing::Gt(0)));
    65      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
    66                  ::testing::AnyOf(SyscallFailsWithErrno(EPIPE),
    67                                   SyscallFailsWithErrno(ECONNRESET)));
    68    });
    69  
    70    // Leave time for write to become blocked.
    71    absl::SleepFor(absl::Seconds(1));
    72  
    73    ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds());
    74  }
    75  
    76  // Random save may interrupt the call to sendmsg() in SendLargeSendMsg(),
    77  // causing the write to be incomplete and the test to hang.
    78  TEST_P(BlockingStreamSocketPairTest, SendMsgTooLarge) {
    79    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    80  
    81    int sndbuf;
    82    socklen_t length = sizeof(sndbuf);
    83    ASSERT_THAT(
    84        getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, &sndbuf, &length),
    85        SyscallSucceeds());
    86  
    87    // Make the call too large to fit in the send buffer.
    88    const int buffer_size = 3 * sndbuf;
    89  
    90    EXPECT_THAT(SendLargeSendMsg(sockets, buffer_size, true /* reader */),
    91                SyscallSucceedsWithValue(buffer_size));
    92  }
    93  
    94  TEST_P(BlockingStreamSocketPairTest, RecvLessThanBuffer) {
    95    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
    96  
    97    char sent_data[100];
    98    RandomizeBuffer(sent_data, sizeof(sent_data));
    99  
   100    ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
   101                SyscallSucceedsWithValue(sizeof(sent_data)));
   102  
   103    char received_data[200] = {};
   104    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   105                                 sizeof(received_data), 0),
   106                SyscallSucceedsWithValue(sizeof(sent_data)));
   107  }
   108  
   109  // Test that MSG_WAITALL causes recv to block until all requested data is
   110  // received. Random save can interrupt blocking and cause received data to be
   111  // returned, even if the amount received is less than the full requested amount.
   112  TEST_P(BlockingStreamSocketPairTest, RecvLessThanBufferWaitAll) {
   113    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   114  
   115    char sent_data[100];
   116    RandomizeBuffer(sent_data, sizeof(sent_data));
   117  
   118    ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
   119                SyscallSucceedsWithValue(sizeof(sent_data)));
   120  
   121    constexpr auto kDuration = absl::Milliseconds(200);
   122    auto before = Now(CLOCK_MONOTONIC);
   123  
   124    const ScopedThread t([&]() {
   125      absl::SleepFor(kDuration);
   126  
   127      // Don't let saving after the write interrupt the blocking recv.
   128      const DisableSave ds;
   129  
   130      ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
   131                  SyscallSucceedsWithValue(sizeof(sent_data)));
   132    });
   133  
   134    char received_data[sizeof(sent_data) * 2] = {};
   135    ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
   136                                 sizeof(received_data), MSG_WAITALL),
   137                SyscallSucceedsWithValue(sizeof(received_data)));
   138  
   139    auto after = Now(CLOCK_MONOTONIC);
   140    EXPECT_GE(after - before, kDuration);
   141  }
   142  
   143  TEST_P(BlockingStreamSocketPairTest, SendTimeout) {
   144    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
   145  
   146    struct timeval tv {
   147      .tv_sec = 0, .tv_usec = 10
   148    };
   149    EXPECT_THAT(
   150        setsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),
   151        SyscallSucceeds());
   152  
   153    std::vector<char> buf(kPageSize);
   154    // We don't know how much data the socketpair will buffer, so we may do an
   155    // arbitrarily large number of writes; saving after each write causes this
   156    // test's time to explode.
   157    const DisableSave ds;
   158    for (;;) {
   159      int ret;
   160      ASSERT_THAT(
   161          ret = RetryEINTR(send)(sockets->first_fd(), buf.data(), buf.size(), 0),
   162          ::testing::AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EAGAIN)));
   163      if (ret == -1) {
   164        break;
   165      }
   166    }
   167  }
   168  
   169  }  // namespace testing
   170  }  // namespace gvisor