github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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/socket_test_util.h" 26 #include "test/syscalls/linux/unix_domain_socket_test_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 int buffer_size; 43 socklen_t length = sizeof(buffer_size); 44 ASSERT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, 45 &buffer_size, &length), 46 SyscallSucceeds()); 47 48 int wfd = sockets->first_fd(); 49 ScopedThread t([wfd, buffer_size]() { 50 std::vector<char> buf(2 * buffer_size); 51 // Write more than fits in the buffer. Blocks then returns partial write 52 // when the other end is closed. The next call returns EPIPE. 53 // 54 // N.B. writes occur in chunks, so we may see less than buffer_size from 55 // the first call. 56 ASSERT_THAT(write(wfd, buf.data(), buf.size()), 57 SyscallSucceedsWithValue(::testing::Gt(0))); 58 ASSERT_THAT(write(wfd, buf.data(), buf.size()), 59 ::testing::AnyOf(SyscallFailsWithErrno(EPIPE), 60 SyscallFailsWithErrno(ECONNRESET))); 61 }); 62 63 // Leave time for write to become blocked. 64 absl::SleepFor(absl::Seconds(1)); 65 66 ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds()); 67 } 68 69 // Random save may interrupt the call to sendmsg() in SendLargeSendMsg(), 70 // causing the write to be incomplete and the test to hang. 71 TEST_P(BlockingStreamSocketPairTest, SendMsgTooLarge) { 72 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 73 74 int sndbuf; 75 socklen_t length = sizeof(sndbuf); 76 ASSERT_THAT( 77 getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, &sndbuf, &length), 78 SyscallSucceeds()); 79 80 // Make the call too large to fit in the send buffer. 81 const int buffer_size = 3 * sndbuf; 82 83 EXPECT_THAT(SendLargeSendMsg(sockets, buffer_size, true /* reader */), 84 SyscallSucceedsWithValue(buffer_size)); 85 } 86 87 TEST_P(BlockingStreamSocketPairTest, RecvLessThanBuffer) { 88 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 89 90 char sent_data[100]; 91 RandomizeBuffer(sent_data, sizeof(sent_data)); 92 93 ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)), 94 SyscallSucceedsWithValue(sizeof(sent_data))); 95 96 char received_data[200] = {}; 97 ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data, 98 sizeof(received_data), 0), 99 SyscallSucceedsWithValue(sizeof(sent_data))); 100 } 101 102 // Test that MSG_WAITALL causes recv to block until all requested data is 103 // received. Random save can interrupt blocking and cause received data to be 104 // returned, even if the amount received is less than the full requested amount. 105 TEST_P(BlockingStreamSocketPairTest, RecvLessThanBufferWaitAll) { 106 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 107 108 char sent_data[100]; 109 RandomizeBuffer(sent_data, sizeof(sent_data)); 110 111 ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)), 112 SyscallSucceedsWithValue(sizeof(sent_data))); 113 114 constexpr auto kDuration = absl::Milliseconds(200); 115 auto before = Now(CLOCK_MONOTONIC); 116 117 const ScopedThread t([&]() { 118 absl::SleepFor(kDuration); 119 120 // Don't let saving after the write interrupt the blocking recv. 121 const DisableSave ds; 122 123 ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)), 124 SyscallSucceedsWithValue(sizeof(sent_data))); 125 }); 126 127 char received_data[sizeof(sent_data) * 2] = {}; 128 ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data, 129 sizeof(received_data), MSG_WAITALL), 130 SyscallSucceedsWithValue(sizeof(received_data))); 131 132 auto after = Now(CLOCK_MONOTONIC); 133 EXPECT_GE(after - before, kDuration); 134 } 135 136 TEST_P(BlockingStreamSocketPairTest, SendTimeout) { 137 auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair()); 138 139 struct timeval tv { 140 .tv_sec = 0, .tv_usec = 10 141 }; 142 EXPECT_THAT( 143 setsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)), 144 SyscallSucceeds()); 145 146 std::vector<char> buf(kPageSize); 147 // We don't know how much data the socketpair will buffer, so we may do an 148 // arbitrarily large number of writes; saving after each write causes this 149 // test's time to explode. 150 const DisableSave ds; 151 for (;;) { 152 int ret; 153 ASSERT_THAT( 154 ret = RetryEINTR(send)(sockets->first_fd(), buf.data(), buf.size(), 0), 155 ::testing::AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EAGAIN))); 156 if (ret == -1) { 157 break; 158 } 159 } 160 } 161 162 } // namespace testing 163 } // namespace gvisor