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