Extract base::UnixSocketRaw
The unix socket class as hit the three-strikes-and-you-refactor
rule (IPC, memory profiler, upcoming logcat).
Extracting a simpler base::UnixSocketRaw class which wraps the
usual send/receive methods, taking care of edge cases (e.g.,
O_CLOEXEC, SIGPIPE, partial writes, EINTR) but which is still
simple enough to avoid requiring a task runner.
This also adds support for kSeqPacket and kDgram types, that
will be used by later CLs for logcat.
Test: perfetto_unittests && perfetto_integrationtests
Bug: 122243384
Change-Id: If0840a5fa6ddb058730e87ed88f3a05addc208d0
diff --git a/src/base/unix_socket_unittest.cc b/src/base/unix_socket_unittest.cc
index feff166..e1fea62 100644
--- a/src/base/unix_socket_unittest.cc
+++ b/src/base/unix_socket_unittest.cc
@@ -18,7 +18,9 @@
#include <signal.h>
#include <sys/mman.h>
-
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
#include <list>
#include <thread>
@@ -265,7 +267,9 @@
}
TEST_F(UnixSocketTest, ListenWithPassedFileDescriptor) {
- auto fd = UnixSocket::CreateAndBind(kSocketName);
+ auto sock_raw = UnixSocketRaw::CreateMayFail(SockType::kStream);
+ ASSERT_TRUE(sock_raw.Bind(kSocketName));
+ auto fd = sock_raw.ReleaseFd();
auto srv = UnixSocket::Listen(std::move(fd), &event_listener_, &task_runner_);
ASSERT_TRUE(srv->is_listening());
@@ -566,7 +570,7 @@
hdr.msg_iov = iov;
hdr.msg_iovlen = base::ArraySize(iov);
- ShiftMsgHdr(1, &hdr);
+ UnixSocketRaw::ShiftMsgHdr(1, &hdr);
EXPECT_NE(hdr.msg_iov, nullptr);
EXPECT_EQ(hdr.msg_iov[0].iov_base, &hello[1]);
EXPECT_EQ(hdr.msg_iov[1].iov_base, &world[0]);
@@ -574,13 +578,13 @@
EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "ello");
EXPECT_EQ(iov[0].iov_len, base::ArraySize(hello) - 1);
- ShiftMsgHdr(base::ArraySize(hello) - 1, &hdr);
+ UnixSocketRaw::ShiftMsgHdr(base::ArraySize(hello) - 1, &hdr);
EXPECT_EQ(hdr.msg_iov, &iov[1]);
EXPECT_EQ(hdr.msg_iovlen, 1);
EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), world);
EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world));
- ShiftMsgHdr(base::ArraySize(world), &hdr);
+ UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world), &hdr);
EXPECT_EQ(hdr.msg_iov, nullptr);
EXPECT_EQ(hdr.msg_iovlen, 0);
}
@@ -600,13 +604,13 @@
hdr.msg_iov = iov;
hdr.msg_iovlen = base::ArraySize(iov);
- ShiftMsgHdr(base::ArraySize(hello) + 1, &hdr);
+ UnixSocketRaw::ShiftMsgHdr(base::ArraySize(hello) + 1, &hdr);
EXPECT_NE(hdr.msg_iov, nullptr);
EXPECT_EQ(hdr.msg_iovlen, 1);
EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "orld");
EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world) - 1);
- ShiftMsgHdr(base::ArraySize(world) - 1, &hdr);
+ UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world) - 1, &hdr);
EXPECT_EQ(hdr.msg_iov, nullptr);
EXPECT_EQ(hdr.msg_iovlen, 0);
}
@@ -626,7 +630,8 @@
hdr.msg_iov = iov;
hdr.msg_iovlen = base::ArraySize(iov);
- ShiftMsgHdr(base::ArraySize(world) + base::ArraySize(hello), &hdr);
+ UnixSocketRaw::ShiftMsgHdr(base::ArraySize(world) + base::ArraySize(hello),
+ &hdr);
EXPECT_EQ(hdr.msg_iov, nullptr);
EXPECT_EQ(hdr.msg_iovlen, 0);
}
@@ -638,17 +643,18 @@
}
TEST_F(UnixSocketTest, PartialSendMsgAll) {
- int sv[2];
- ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0);
- base::ScopedFile send_socket(sv[0]);
- base::ScopedFile recv_socket(sv[1]);
+ UnixSocketRaw send_sock;
+ UnixSocketRaw recv_sock;
+ std::tie(send_sock, recv_sock) = UnixSocketRaw::CreatePair(SockType::kStream);
+ ASSERT_TRUE(send_sock);
+ ASSERT_TRUE(recv_sock);
// Set bufsize to minimum.
int bufsize = 1024;
- ASSERT_EQ(setsockopt(*send_socket, SOL_SOCKET, SO_SNDBUF, &bufsize,
+ ASSERT_EQ(setsockopt(send_sock.fd(), SOL_SOCKET, SO_SNDBUF, &bufsize,
sizeof(bufsize)),
0);
- ASSERT_EQ(setsockopt(*recv_socket, SOL_SOCKET, SO_RCVBUF, &bufsize,
+ ASSERT_EQ(setsockopt(recv_sock.fd(), SOL_SOCKET, SO_RCVBUF, &bufsize,
sizeof(bufsize)),
0);
@@ -674,8 +680,8 @@
rollback(&oldact);
auto blocked_thread = pthread_self();
- std::thread th([blocked_thread, &recv_socket, &recv_buf] {
- ssize_t rd = PERFETTO_EINTR(read(*recv_socket, recv_buf, 1));
+ std::thread th([blocked_thread, &recv_sock, &recv_buf] {
+ ssize_t rd = PERFETTO_EINTR(read(recv_sock.fd(), recv_buf, 1));
ASSERT_EQ(rd, 1);
// We are now sure the other thread is in sendmsg, interrupt send.
ASSERT_EQ(pthread_kill(blocked_thread, SIGWINCH), 0);
@@ -683,7 +689,7 @@
size_t offset = 1;
while (offset < sizeof(recv_buf)) {
rd = PERFETTO_EINTR(
- read(*recv_socket, recv_buf + offset, sizeof(recv_buf) - offset));
+ read(recv_sock.fd(), recv_buf + offset, sizeof(recv_buf) - offset));
ASSERT_GE(rd, 0);
offset += static_cast<size_t>(rd);
}
@@ -703,8 +709,8 @@
hdr.msg_iov = iov;
hdr.msg_iovlen = base::ArraySize(iov);
- ASSERT_EQ(SendMsgAll(*send_socket, &hdr, 0), sizeof(send_buf));
- send_socket.reset();
+ ASSERT_EQ(send_sock.SendMsgAll(&hdr), sizeof(send_buf));
+ send_sock.Shutdown();
th.join();
// Make sure the re-entry logic was actually triggered.
ASSERT_EQ(hdr.msg_iov, nullptr);