Fix socket_ipv4_udp_unbound_loopback_test_linux

Handle "Resource temporarily unavailable" EAGAIN errors with a select
call before calling recvmsg.

Also rename similar helper call from "RecvMsgTimeout" to "RecvTimeout",
because it calls "recv".

PiperOrigin-RevId: 338761695
This commit is contained in:
Zach Koopmans
2020-10-23 16:13:46 -07:00
committed by Nicolas Lacasse
parent a04c8ad4ce
commit 634e14a094
4 changed files with 67 additions and 53 deletions
+38 -38
View File
@@ -75,7 +75,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackNoGroup) {
// Check that we did not receive the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
EXPECT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
@@ -209,7 +209,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackAddr) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -265,7 +265,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackNic) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -321,7 +321,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfAddr) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -377,7 +377,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfNic) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -437,7 +437,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfAddrConnect) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -497,7 +497,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfNicConnect) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -553,7 +553,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfAddrSelf) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -609,7 +609,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfNicSelf) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -669,7 +669,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfAddrSelfConnect) {
// Check that we did not receive the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
EXPECT_THAT(
RecvMsgTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
@@ -727,7 +727,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfNicSelfConnect) {
// Check that we did not receive the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
EXPECT_THAT(
RecvMsgTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
@@ -785,7 +785,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfAddrSelfNoLoop) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -845,7 +845,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastLoopbackIfNicSelfNoLoop) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
@@ -919,7 +919,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastDropAddr) {
// Check that we did not receive the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
EXPECT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
@@ -977,7 +977,7 @@ TEST_P(IPv4UDPUnboundSocketTest, IpMulticastDropNic) {
// Check that we did not receive the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
EXPECT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
@@ -1330,8 +1330,8 @@ TEST_P(IPv4UDPUnboundSocketTest, TestMcastReceptionOnTwoSockets) {
// Check that we received the multicast packet on both sockets.
for (auto& sockets : socket_pairs) {
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(RecvMsgTimeout(sockets->second_fd(), recv_buf,
sizeof(recv_buf), 1 /*timeout*/),
ASSERT_THAT(RecvTimeout(sockets->second_fd(), recv_buf, sizeof(recv_buf),
1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
@@ -1409,8 +1409,8 @@ TEST_P(IPv4UDPUnboundSocketTest, TestMcastReceptionWhenDroppingMemberships) {
// Check that we received the multicast packet on both sockets.
for (auto& sockets : socket_pairs) {
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(RecvMsgTimeout(sockets->second_fd(), recv_buf,
sizeof(recv_buf), 1 /*timeout*/),
ASSERT_THAT(RecvTimeout(sockets->second_fd(), recv_buf, sizeof(recv_buf),
1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
@@ -1432,8 +1432,8 @@ TEST_P(IPv4UDPUnboundSocketTest, TestMcastReceptionWhenDroppingMemberships) {
char recv_buf[sizeof(send_buf)] = {};
for (auto& sockets : socket_pairs) {
ASSERT_THAT(RecvMsgTimeout(sockets->second_fd(), recv_buf,
sizeof(recv_buf), 1 /*timeout*/),
ASSERT_THAT(RecvTimeout(sockets->second_fd(), recv_buf, sizeof(recv_buf),
1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
}
@@ -1486,7 +1486,7 @@ TEST_P(IPv4UDPUnboundSocketTest, TestBindToMcastThenJoinThenReceive) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
@@ -1530,7 +1530,7 @@ TEST_P(IPv4UDPUnboundSocketTest, TestBindToMcastThenNoJoinThenNoReceive) {
// Check that we don't receive the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
@@ -1580,7 +1580,7 @@ TEST_P(IPv4UDPUnboundSocketTest, TestBindToMcastThenSend) {
// Check that we received the packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
@@ -1627,7 +1627,7 @@ TEST_P(IPv4UDPUnboundSocketTest, TestBindToBcastThenReceive) {
// Check that we received the multicast packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
@@ -1678,7 +1678,7 @@ TEST_P(IPv4UDPUnboundSocketTest, TestBindToBcastThenSend) {
// Check that we received the packet.
char recv_buf[sizeof(send_buf)] = {};
ASSERT_THAT(
RecvMsgTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(socket2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(recv_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
@@ -1737,7 +1737,7 @@ TEST_P(IPv4UDPUnboundSocketTest, ReuseAddrDistribution_NoRandomSave) {
// of the other sockets to have received it, but we will check that later.
char recv_buf[sizeof(send_buf)] = {};
EXPECT_THAT(
RecvMsgTimeout(last->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
RecvTimeout(last->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(send_buf)));
EXPECT_EQ(0, memcmp(send_buf, recv_buf, sizeof(send_buf)));
}
@@ -1745,9 +1745,9 @@ TEST_P(IPv4UDPUnboundSocketTest, ReuseAddrDistribution_NoRandomSave) {
// Verify that no other messages were received.
for (auto& socket : sockets) {
char recv_buf[kMessageSize] = {};
EXPECT_THAT(RecvMsgTimeout(socket->get(), recv_buf, sizeof(recv_buf),
1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
EXPECT_THAT(
RecvTimeout(socket->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
PosixErrorIs(EAGAIN, ::testing::_));
}
}
@@ -2124,12 +2124,12 @@ TEST_P(IPv4UDPUnboundSocketTest, ReuseAddrReusePortDistribution) {
// balancing (REUSEPORT) instead of the most recently bound socket
// (REUSEADDR).
char recv_buf[kMessageSize] = {};
EXPECT_THAT(RecvMsgTimeout(receiver1->get(), recv_buf, sizeof(recv_buf),
1 /*timeout*/),
IsPosixErrorOkAndHolds(kMessageSize));
EXPECT_THAT(RecvMsgTimeout(receiver2->get(), recv_buf, sizeof(recv_buf),
1 /*timeout*/),
IsPosixErrorOkAndHolds(kMessageSize));
EXPECT_THAT(
RecvTimeout(receiver1->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(kMessageSize));
EXPECT_THAT(
RecvTimeout(receiver2->get(), recv_buf, sizeof(recv_buf), 1 /*timeout*/),
IsPosixErrorOkAndHolds(kMessageSize));
}
// Test that socket will receive packet info control message.
@@ -2193,8 +2193,8 @@ TEST_P(IPv4UDPUnboundSocketTest, SetAndReceiveIPPKTINFO) {
received_msg.msg_controllen = CMSG_LEN(cmsg_data_len);
received_msg.msg_control = received_cmsg_buf;
ASSERT_THAT(RetryEINTR(recvmsg)(receiver->get(), &received_msg, 0),
SyscallSucceedsWithValue(kDataLength));
ASSERT_THAT(RecvMsgTimeout(receiver->get(), &received_msg, 1 /*timeout*/),
IsPosixErrorOkAndHolds(kDataLength));
cmsghdr* cmsg = CMSG_FIRSTHDR(&received_msg);
ASSERT_NE(cmsg, nullptr);
+14 -2
View File
@@ -753,8 +753,7 @@ PosixErrorOr<int> SendMsg(int sock, msghdr* msg, char buf[], int buf_size) {
return ret;
}
PosixErrorOr<int> RecvMsgTimeout(int sock, char buf[], int buf_size,
int timeout) {
PosixErrorOr<int> RecvTimeout(int sock, char buf[], int buf_size, int timeout) {
fd_set rfd;
struct timeval to = {.tv_sec = timeout, .tv_usec = 0};
FD_ZERO(&rfd);
@@ -767,6 +766,19 @@ PosixErrorOr<int> RecvMsgTimeout(int sock, char buf[], int buf_size,
return ret;
}
PosixErrorOr<int> RecvMsgTimeout(int sock, struct msghdr* msg, int timeout) {
fd_set rfd;
struct timeval to = {.tv_sec = timeout, .tv_usec = 0};
FD_ZERO(&rfd);
FD_SET(sock, &rfd);
int ret;
RETURN_ERROR_IF_SYSCALL_FAIL(ret = select(1, &rfd, NULL, NULL, &to));
RETURN_ERROR_IF_SYSCALL_FAIL(
ret = RetryEINTR(recvmsg)(sock, msg, MSG_DONTWAIT));
return ret;
}
void RecvNoData(int sock) {
char data = 0;
struct iovec iov;
+6 -3
View File
@@ -467,9 +467,12 @@ PosixError FreeAvailablePort(int port);
// SendMsg converts a buffer to an iovec and adds it to msg before sending it.
PosixErrorOr<int> SendMsg(int sock, msghdr* msg, char buf[], int buf_size);
// RecvMsgTimeout calls select on sock with timeout and then calls recv on sock.
PosixErrorOr<int> RecvMsgTimeout(int sock, char buf[], int buf_size,
int timeout);
// RecvTimeout calls select on sock with timeout and then calls recv on sock.
PosixErrorOr<int> RecvTimeout(int sock, char buf[], int buf_size, int timeout);
// RecvMsgTimeout calls select on sock with timeout and then calls recvmsg on
// sock.
PosixErrorOr<int> RecvMsgTimeout(int sock, msghdr* msg, int timeout);
// RecvNoData checks that no data is receivable on sock.
void RecvNoData(int sock);
+9 -10
View File
@@ -838,7 +838,7 @@ TEST_P(UdpSocketTest, ReceiveBeforeConnect) {
// Receive the data. It works because it was sent before the connect.
char received[sizeof(buf)];
EXPECT_THAT(
RecvMsgTimeout(bind_.get(), received, sizeof(received), 1 /*timeout*/),
RecvTimeout(bind_.get(), received, sizeof(received), 1 /*timeout*/),
IsPosixErrorOkAndHolds(sizeof(received)));
EXPECT_EQ(memcmp(buf, received, sizeof(buf)), 0);
@@ -928,9 +928,8 @@ TEST_P(UdpSocketTest, ReadShutdownNonblockPendingData) {
SyscallSucceedsWithValue(1));
// We should get the data even though read has been shutdown.
EXPECT_THAT(
RecvMsgTimeout(bind_.get(), received, 2 /*buf_size*/, 1 /*timeout*/),
IsPosixErrorOkAndHolds(2));
EXPECT_THAT(RecvTimeout(bind_.get(), received, 2 /*buf_size*/, 1 /*timeout*/),
IsPosixErrorOkAndHolds(2));
// Because we read less than the entire packet length, since it's a packet
// based socket any subsequent reads should return EWOULDBLOCK.
@@ -1698,8 +1697,8 @@ TEST_P(UdpSocketTest, RecvBufLimitsEmptyRcvBuf) {
sendto(sock_.get(), buf.data(), buf.size(), 0, bind_addr_, addrlen_),
SyscallSucceedsWithValue(buf.size()));
std::vector<char> received(buf.size());
EXPECT_THAT(RecvMsgTimeout(bind_.get(), received.data(), received.size(),
1 /*timeout*/),
EXPECT_THAT(RecvTimeout(bind_.get(), received.data(), received.size(),
1 /*timeout*/),
IsPosixErrorOkAndHolds(received.size()));
}
@@ -1714,8 +1713,8 @@ TEST_P(UdpSocketTest, RecvBufLimitsEmptyRcvBuf) {
SyscallSucceedsWithValue(buf.size()));
std::vector<char> received(buf.size());
ASSERT_THAT(RecvMsgTimeout(bind_.get(), received.data(), received.size(),
1 /*timeout*/),
ASSERT_THAT(RecvTimeout(bind_.get(), received.data(), received.size(),
1 /*timeout*/),
IsPosixErrorOkAndHolds(received.size()));
}
}
@@ -1785,8 +1784,8 @@ TEST_P(UdpSocketTest, RecvBufLimits) {
for (int i = 0; i < sent - 1; i++) {
// Receive the data.
std::vector<char> received(buf.size());
EXPECT_THAT(RecvMsgTimeout(bind_.get(), received.data(), received.size(),
1 /*timeout*/),
EXPECT_THAT(RecvTimeout(bind_.get(), received.data(), received.size(),
1 /*timeout*/),
IsPosixErrorOkAndHolds(received.size()));
EXPECT_EQ(memcmp(buf.data(), received.data(), buf.size()), 0);
}