[llvm] [llvm][Support] Implement raw_socket_stream::read with optional timeout (PR #92308)
Connor Sughrue via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 17 18:01:27 PDT 2024
https://github.com/cpsughrue updated https://github.com/llvm/llvm-project/pull/92308
>From a7f9b96dea4a090ad1ff9c1d06cb7584c8f1fed5 Mon Sep 17 00:00:00 2001
From: cpsughrue <cpsughrue at gmail.com>
Date: Wed, 29 May 2024 09:26:07 -0400
Subject: [PATCH 1/7] WIP
---
llvm/include/llvm/Support/FileDescriptor.h | 32 +++++++
llvm/lib/Support/CMakeLists.txt | 3 +-
llvm/lib/Support/FileDescriptor.cpp | 91 +++++++++++++++++++
llvm/lib/Support/raw_socket_stream.cpp | 62 +------------
.../gn/secondary/llvm/lib/Support/BUILD.gn | 1 +
5 files changed, 130 insertions(+), 59 deletions(-)
create mode 100644 llvm/include/llvm/Support/FileDescriptor.h
create mode 100644 llvm/lib/Support/FileDescriptor.cpp
diff --git a/llvm/include/llvm/Support/FileDescriptor.h b/llvm/include/llvm/Support/FileDescriptor.h
new file mode 100644
index 0000000000000..ab83b34fca0fa
--- /dev/null
+++ b/llvm/include/llvm/Support/FileDescriptor.h
@@ -0,0 +1,32 @@
+//===-- FileDescriptor.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a utility functions for working with file descriptors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_FILEDESCRIPTOR_H
+#define LLVM_SUPPORT_FILEDESCRIPTOR_H
+
+#include "llvm/Support/Error.h"
+#include <chrono>
+
+namespace llvm {
+// Helper function to get the value from either std::atomic<int> or int
+template <typename T> int getFD(T &FD) {
+ if constexpr (std::is_same_v<T, std::atomic<int>>) {
+ return FD.load();
+ } else {
+ return FD;
+ }
+}
+
+template <typename T>
+llvm::Error manageTimeout(std::chrono::milliseconds Timeout, T &FD, int PipeFD);
+} // namespace llvm
+#endif
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index be4badc09efa5..0a65e58da88a8 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -176,8 +176,9 @@ add_llvm_component_library(LLVMSupport
ExponentialBackoff.cpp
ExtensibleRTTI.cpp
FileCollector.cpp
- FileUtilities.cpp
+ FileDescriptor.cpp
FileOutputBuffer.cpp
+ FileUtilities.cpp
FloatingPointMode.cpp
FoldingSet.cpp
FormattedStream.cpp
diff --git a/llvm/lib/Support/FileDescriptor.cpp b/llvm/lib/Support/FileDescriptor.cpp
new file mode 100644
index 0000000000000..9ecf991fa5dc3
--- /dev/null
+++ b/llvm/lib/Support/FileDescriptor.cpp
@@ -0,0 +1,91 @@
+//===-- FileDescriptor.cpp --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a utility functions for working with file descriptors
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileDescriptor.h"
+#include <atomic>
+#include <chrono>
+#include <poll.h>
+
+static std::error_code getLastSocketErrorCode() {
+#ifdef _WIN32
+ return std::error_code(::WSAGetLastError(), std::system_category());
+#else
+ return llvm::errnoAsErrorCode();
+#endif
+}
+
+template <typename T>
+llvm::Error llvm::manageTimeout(std::chrono::milliseconds Timeout, T &FD, int PipeFD) {
+ static_assert(std::is_same_v<T, int> || std::is_same_v<T, std::atomic<int>>,
+ "FD must be of type int& or std::atomic<int>&");
+
+ struct pollfd FDs[2];
+ FDs[0].events = POLLIN;
+#ifdef _WIN32
+ SOCKET WinServerSock = _get_osfhandle(FD);
+ FDs[0].fd = WinServerSock;
+#else
+ FDs[0].fd = llvm::getFD(FD);
+#endif
+ FDs[1].events = POLLIN;
+ FDs[1].fd = PipeFD;
+
+ // Keep track of how much time has passed in case poll is interupted by a
+ // signal and needs to be recalled
+ int RemainingTime = Timeout.count();
+ std::chrono::milliseconds ElapsedTime = std::chrono::milliseconds(0);
+ int PollStatus = -1;
+
+ while (PollStatus == -1 && (Timeout.count() == -1 || ElapsedTime < Timeout)) {
+ if (Timeout.count() != -1)
+ RemainingTime -= ElapsedTime.count();
+
+ auto Start = std::chrono::steady_clock::now();
+#ifdef _WIN32
+ PollStatus = WSAPoll(FDs, 2, RemainingTime);
+#else
+ PollStatus = ::poll(FDs, 2, RemainingTime);
+#endif
+ // If FD equals -1 then ListeningSocket::shutdown has been called and it is
+ // appropriate to return operation_canceled
+ if (FD == -1)
+ return llvm::make_error<llvm::StringError>(
+ std::make_error_code(std::errc::operation_canceled),
+ "Accept canceled");
+
+#if _WIN32
+ if (PollStatus == SOCKET_ERROR) {
+#else
+ if (PollStatus == -1) {
+#endif
+ std::error_code PollErrCode = getLastSocketErrorCode();
+ // Ignore EINTR (signal occured before any request event) and retry
+ if (PollErrCode != std::errc::interrupted)
+ return llvm::make_error<llvm::StringError>(PollErrCode,
+ "FD poll failed");
+ }
+ if (PollStatus == 0)
+ return llvm::make_error<llvm::StringError>(
+ std::make_error_code(std::errc::timed_out),
+ "No client requests within timeout window");
+
+ if (FDs[0].revents & POLLNVAL)
+ return llvm::make_error<llvm::StringError>(
+ std::make_error_code(std::errc::bad_file_descriptor));
+
+ auto Stop = std::chrono::steady_clock::now();
+ ElapsedTime +=
+ std::chrono::duration_cast<std::chrono::milliseconds>(Stop - Start);
+ }
+ return llvm::Error::success();
+}
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 549d537709bf2..4f1b24377bd5e 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -14,6 +14,7 @@
#include "llvm/Support/raw_socket_stream.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Error.h"
+#include "llvm/Support/FileDescriptor.h"
#include "llvm/Support/FileSystem.h"
#include <atomic>
@@ -179,64 +180,9 @@ Expected<ListeningSocket> ListeningSocket::createUnix(StringRef SocketPath,
Expected<std::unique_ptr<raw_socket_stream>>
ListeningSocket::accept(std::chrono::milliseconds Timeout) {
-
- struct pollfd FDs[2];
- FDs[0].events = POLLIN;
-#ifdef _WIN32
- SOCKET WinServerSock = _get_osfhandle(FD);
- FDs[0].fd = WinServerSock;
-#else
- FDs[0].fd = FD;
-#endif
- FDs[1].events = POLLIN;
- FDs[1].fd = PipeFD[0];
-
- // Keep track of how much time has passed in case poll is interupted by a
- // signal and needs to be recalled
- int RemainingTime = Timeout.count();
- std::chrono::milliseconds ElapsedTime = std::chrono::milliseconds(0);
- int PollStatus = -1;
-
- while (PollStatus == -1 && (Timeout.count() == -1 || ElapsedTime < Timeout)) {
- if (Timeout.count() != -1)
- RemainingTime -= ElapsedTime.count();
-
- auto Start = std::chrono::steady_clock::now();
-#ifdef _WIN32
- PollStatus = WSAPoll(FDs, 2, RemainingTime);
-#else
- PollStatus = ::poll(FDs, 2, RemainingTime);
-#endif
- // If FD equals -1 then ListeningSocket::shutdown has been called and it is
- // appropriate to return operation_canceled
- if (FD.load() == -1)
- return llvm::make_error<StringError>(
- std::make_error_code(std::errc::operation_canceled),
- "Accept canceled");
-
-#if _WIN32
- if (PollStatus == SOCKET_ERROR) {
-#else
- if (PollStatus == -1) {
-#endif
- std::error_code PollErrCode = getLastSocketErrorCode();
- // Ignore EINTR (signal occured before any request event) and retry
- if (PollErrCode != std::errc::interrupted)
- return llvm::make_error<StringError>(PollErrCode, "FD poll failed");
- }
- if (PollStatus == 0)
- return llvm::make_error<StringError>(
- std::make_error_code(std::errc::timed_out),
- "No client requests within timeout window");
-
- if (FDs[0].revents & POLLNVAL)
- return llvm::make_error<StringError>(
- std::make_error_code(std::errc::bad_file_descriptor));
-
- auto Stop = std::chrono::steady_clock::now();
- ElapsedTime +=
- std::chrono::duration_cast<std::chrono::milliseconds>(Stop - Start);
- }
+ llvm::Error TimeoutErr = manageTimeout(Timeout, FD, PipeFD[0]);
+ // if (TimeoutErr)
+ // return TimeoutErr;
int AcceptFD;
#ifdef _WIN32
diff --git a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
index 7728455499bf3..79259abb80022 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
@@ -80,6 +80,7 @@ static_library("Support") {
"ExponentialBackoff.cpp",
"ExtensibleRTTI.cpp",
"FileCollector.cpp",
+ "FileDescriptor.cpp",
"FileOutputBuffer.cpp",
"FileUtilities.cpp",
"FloatingPointMode.cpp",
>From d76de7f29d5ae39533605a2aaddb845dcc80efeb Mon Sep 17 00:00:00 2001
From: cpsughrue <cpsughrue at gmail.com>
Date: Sun, 2 Jun 2024 13:58:31 -0400
Subject: [PATCH 2/7] Revert "WIP"
This reverts commit a7f9b96dea4a090ad1ff9c1d06cb7584c8f1fed5.
---
llvm/include/llvm/Support/FileDescriptor.h | 32 -------
llvm/lib/Support/CMakeLists.txt | 3 +-
llvm/lib/Support/FileDescriptor.cpp | 91 -------------------
llvm/lib/Support/raw_socket_stream.cpp | 62 ++++++++++++-
.../gn/secondary/llvm/lib/Support/BUILD.gn | 1 -
5 files changed, 59 insertions(+), 130 deletions(-)
delete mode 100644 llvm/include/llvm/Support/FileDescriptor.h
delete mode 100644 llvm/lib/Support/FileDescriptor.cpp
diff --git a/llvm/include/llvm/Support/FileDescriptor.h b/llvm/include/llvm/Support/FileDescriptor.h
deleted file mode 100644
index ab83b34fca0fa..0000000000000
--- a/llvm/include/llvm/Support/FileDescriptor.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===-- FileDescriptor.h ----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains a utility functions for working with file descriptors
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_SUPPORT_FILEDESCRIPTOR_H
-#define LLVM_SUPPORT_FILEDESCRIPTOR_H
-
-#include "llvm/Support/Error.h"
-#include <chrono>
-
-namespace llvm {
-// Helper function to get the value from either std::atomic<int> or int
-template <typename T> int getFD(T &FD) {
- if constexpr (std::is_same_v<T, std::atomic<int>>) {
- return FD.load();
- } else {
- return FD;
- }
-}
-
-template <typename T>
-llvm::Error manageTimeout(std::chrono::milliseconds Timeout, T &FD, int PipeFD);
-} // namespace llvm
-#endif
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index 0a65e58da88a8..be4badc09efa5 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -176,9 +176,8 @@ add_llvm_component_library(LLVMSupport
ExponentialBackoff.cpp
ExtensibleRTTI.cpp
FileCollector.cpp
- FileDescriptor.cpp
- FileOutputBuffer.cpp
FileUtilities.cpp
+ FileOutputBuffer.cpp
FloatingPointMode.cpp
FoldingSet.cpp
FormattedStream.cpp
diff --git a/llvm/lib/Support/FileDescriptor.cpp b/llvm/lib/Support/FileDescriptor.cpp
deleted file mode 100644
index 9ecf991fa5dc3..0000000000000
--- a/llvm/lib/Support/FileDescriptor.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-//===-- FileDescriptor.cpp --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains a utility functions for working with file descriptors
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileDescriptor.h"
-#include <atomic>
-#include <chrono>
-#include <poll.h>
-
-static std::error_code getLastSocketErrorCode() {
-#ifdef _WIN32
- return std::error_code(::WSAGetLastError(), std::system_category());
-#else
- return llvm::errnoAsErrorCode();
-#endif
-}
-
-template <typename T>
-llvm::Error llvm::manageTimeout(std::chrono::milliseconds Timeout, T &FD, int PipeFD) {
- static_assert(std::is_same_v<T, int> || std::is_same_v<T, std::atomic<int>>,
- "FD must be of type int& or std::atomic<int>&");
-
- struct pollfd FDs[2];
- FDs[0].events = POLLIN;
-#ifdef _WIN32
- SOCKET WinServerSock = _get_osfhandle(FD);
- FDs[0].fd = WinServerSock;
-#else
- FDs[0].fd = llvm::getFD(FD);
-#endif
- FDs[1].events = POLLIN;
- FDs[1].fd = PipeFD;
-
- // Keep track of how much time has passed in case poll is interupted by a
- // signal and needs to be recalled
- int RemainingTime = Timeout.count();
- std::chrono::milliseconds ElapsedTime = std::chrono::milliseconds(0);
- int PollStatus = -1;
-
- while (PollStatus == -1 && (Timeout.count() == -1 || ElapsedTime < Timeout)) {
- if (Timeout.count() != -1)
- RemainingTime -= ElapsedTime.count();
-
- auto Start = std::chrono::steady_clock::now();
-#ifdef _WIN32
- PollStatus = WSAPoll(FDs, 2, RemainingTime);
-#else
- PollStatus = ::poll(FDs, 2, RemainingTime);
-#endif
- // If FD equals -1 then ListeningSocket::shutdown has been called and it is
- // appropriate to return operation_canceled
- if (FD == -1)
- return llvm::make_error<llvm::StringError>(
- std::make_error_code(std::errc::operation_canceled),
- "Accept canceled");
-
-#if _WIN32
- if (PollStatus == SOCKET_ERROR) {
-#else
- if (PollStatus == -1) {
-#endif
- std::error_code PollErrCode = getLastSocketErrorCode();
- // Ignore EINTR (signal occured before any request event) and retry
- if (PollErrCode != std::errc::interrupted)
- return llvm::make_error<llvm::StringError>(PollErrCode,
- "FD poll failed");
- }
- if (PollStatus == 0)
- return llvm::make_error<llvm::StringError>(
- std::make_error_code(std::errc::timed_out),
- "No client requests within timeout window");
-
- if (FDs[0].revents & POLLNVAL)
- return llvm::make_error<llvm::StringError>(
- std::make_error_code(std::errc::bad_file_descriptor));
-
- auto Stop = std::chrono::steady_clock::now();
- ElapsedTime +=
- std::chrono::duration_cast<std::chrono::milliseconds>(Stop - Start);
- }
- return llvm::Error::success();
-}
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 4f1b24377bd5e..549d537709bf2 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -14,7 +14,6 @@
#include "llvm/Support/raw_socket_stream.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Error.h"
-#include "llvm/Support/FileDescriptor.h"
#include "llvm/Support/FileSystem.h"
#include <atomic>
@@ -180,9 +179,64 @@ Expected<ListeningSocket> ListeningSocket::createUnix(StringRef SocketPath,
Expected<std::unique_ptr<raw_socket_stream>>
ListeningSocket::accept(std::chrono::milliseconds Timeout) {
- llvm::Error TimeoutErr = manageTimeout(Timeout, FD, PipeFD[0]);
- // if (TimeoutErr)
- // return TimeoutErr;
+
+ struct pollfd FDs[2];
+ FDs[0].events = POLLIN;
+#ifdef _WIN32
+ SOCKET WinServerSock = _get_osfhandle(FD);
+ FDs[0].fd = WinServerSock;
+#else
+ FDs[0].fd = FD;
+#endif
+ FDs[1].events = POLLIN;
+ FDs[1].fd = PipeFD[0];
+
+ // Keep track of how much time has passed in case poll is interupted by a
+ // signal and needs to be recalled
+ int RemainingTime = Timeout.count();
+ std::chrono::milliseconds ElapsedTime = std::chrono::milliseconds(0);
+ int PollStatus = -1;
+
+ while (PollStatus == -1 && (Timeout.count() == -1 || ElapsedTime < Timeout)) {
+ if (Timeout.count() != -1)
+ RemainingTime -= ElapsedTime.count();
+
+ auto Start = std::chrono::steady_clock::now();
+#ifdef _WIN32
+ PollStatus = WSAPoll(FDs, 2, RemainingTime);
+#else
+ PollStatus = ::poll(FDs, 2, RemainingTime);
+#endif
+ // If FD equals -1 then ListeningSocket::shutdown has been called and it is
+ // appropriate to return operation_canceled
+ if (FD.load() == -1)
+ return llvm::make_error<StringError>(
+ std::make_error_code(std::errc::operation_canceled),
+ "Accept canceled");
+
+#if _WIN32
+ if (PollStatus == SOCKET_ERROR) {
+#else
+ if (PollStatus == -1) {
+#endif
+ std::error_code PollErrCode = getLastSocketErrorCode();
+ // Ignore EINTR (signal occured before any request event) and retry
+ if (PollErrCode != std::errc::interrupted)
+ return llvm::make_error<StringError>(PollErrCode, "FD poll failed");
+ }
+ if (PollStatus == 0)
+ return llvm::make_error<StringError>(
+ std::make_error_code(std::errc::timed_out),
+ "No client requests within timeout window");
+
+ if (FDs[0].revents & POLLNVAL)
+ return llvm::make_error<StringError>(
+ std::make_error_code(std::errc::bad_file_descriptor));
+
+ auto Stop = std::chrono::steady_clock::now();
+ ElapsedTime +=
+ std::chrono::duration_cast<std::chrono::milliseconds>(Stop - Start);
+ }
int AcceptFD;
#ifdef _WIN32
diff --git a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
index 79259abb80022..7728455499bf3 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Support/BUILD.gn
@@ -80,7 +80,6 @@ static_library("Support") {
"ExponentialBackoff.cpp",
"ExtensibleRTTI.cpp",
"FileCollector.cpp",
- "FileDescriptor.cpp",
"FileOutputBuffer.cpp",
"FileUtilities.cpp",
"FloatingPointMode.cpp",
>From 1249e4d1fa4aa330ff3d8008ccd49b98514bacd5 Mon Sep 17 00:00:00 2001
From: cpsughrue <cpsughrue at gmail.com>
Date: Sun, 2 Jun 2024 15:04:21 -0400
Subject: [PATCH 3/7] Create static manageTimeout function
---
llvm/lib/Support/raw_socket_stream.cpp | 44 +++++++++++++++-----------
1 file changed, 26 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 549d537709bf2..76f148acf491b 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -177,43 +177,43 @@ Expected<ListeningSocket> ListeningSocket::createUnix(StringRef SocketPath,
#endif // _WIN32
}
-Expected<std::unique_ptr<raw_socket_stream>>
-ListeningSocket::accept(std::chrono::milliseconds Timeout) {
-
- struct pollfd FDs[2];
- FDs[0].events = POLLIN;
+static llvm::Error manageTimeout(std::atomic<int> &ActiveFD, int CancelFD,
+ std::chrono::milliseconds Timeout) {
+ struct pollfd FD[2];
+ FD[0].events = POLLIN;
#ifdef _WIN32
SOCKET WinServerSock = _get_osfhandle(FD);
- FDs[0].fd = WinServerSock;
+ FD[0].fd = WinServerSock;
#else
- FDs[0].fd = FD;
+ FD[0].fd = ActiveFD.load();
#endif
- FDs[1].events = POLLIN;
- FDs[1].fd = PipeFD[0];
+ FD[1].events = POLLIN;
+ FD[1].fd = CancelFD;
- // Keep track of how much time has passed in case poll is interupted by a
- // signal and needs to be recalled
+ // Keep track of how much time has passed in case ::poll or WSAPoll are
+ // interupted by a signal and need to be recalled
int RemainingTime = Timeout.count();
std::chrono::milliseconds ElapsedTime = std::chrono::milliseconds(0);
int PollStatus = -1;
while (PollStatus == -1 && (Timeout.count() == -1 || ElapsedTime < Timeout)) {
+ // Timeout of -1 indicates that no Timeout was provided
if (Timeout.count() != -1)
RemainingTime -= ElapsedTime.count();
-
auto Start = std::chrono::steady_clock::now();
+
#ifdef _WIN32
- PollStatus = WSAPoll(FDs, 2, RemainingTime);
+ PollStatus = WSAPoll(FD, 2, RemainingTime);
#else
- PollStatus = ::poll(FDs, 2, RemainingTime);
+ PollStatus = ::poll(FD, 2, RemainingTime);
#endif
+
// If FD equals -1 then ListeningSocket::shutdown has been called and it is
// appropriate to return operation_canceled
- if (FD.load() == -1)
+ if (ActiveFD.load() == -1)
return llvm::make_error<StringError>(
std::make_error_code(std::errc::operation_canceled),
"Accept canceled");
-
#if _WIN32
if (PollStatus == SOCKET_ERROR) {
#else
@@ -222,14 +222,14 @@ ListeningSocket::accept(std::chrono::milliseconds Timeout) {
std::error_code PollErrCode = getLastSocketErrorCode();
// Ignore EINTR (signal occured before any request event) and retry
if (PollErrCode != std::errc::interrupted)
- return llvm::make_error<StringError>(PollErrCode, "FD poll failed");
+ return llvm::make_error<StringError>(PollErrCode, "poll failed");
}
if (PollStatus == 0)
return llvm::make_error<StringError>(
std::make_error_code(std::errc::timed_out),
"No client requests within timeout window");
- if (FDs[0].revents & POLLNVAL)
+ if (FD[0].revents & POLLNVAL)
return llvm::make_error<StringError>(
std::make_error_code(std::errc::bad_file_descriptor));
@@ -237,6 +237,14 @@ ListeningSocket::accept(std::chrono::milliseconds Timeout) {
ElapsedTime +=
std::chrono::duration_cast<std::chrono::milliseconds>(Stop - Start);
}
+ return llvm::Error::success();
+}
+
+Expected<std::unique_ptr<raw_socket_stream>>
+ListeningSocket::accept(std::chrono::milliseconds Timeout) {
+ llvm::Error TimeoutErr = manageTimeout(FD, PipeFD[0], Timeout);
+ if (TimeoutErr)
+ return TimeoutErr;
int AcceptFD;
#ifdef _WIN32
>From 5d6749e63e5c725f0092bd290c60974dfdc8fdff Mon Sep 17 00:00:00 2001
From: cpsughrue <cpsughrue at gmail.com>
Date: Sun, 2 Jun 2024 22:06:42 -0400
Subject: [PATCH 4/7] Initial implementation of
raw_socket_stream::readFromSocket with timeout
---
llvm/include/llvm/Support/raw_socket_stream.h | 21 +++-
llvm/lib/Support/raw_socket_stream.cpp | 62 ++++++++--
.../Support/raw_socket_stream_test.cpp | 107 ++++++++++++++++--
3 files changed, 164 insertions(+), 26 deletions(-)
diff --git a/llvm/include/llvm/Support/raw_socket_stream.h b/llvm/include/llvm/Support/raw_socket_stream.h
index bddd47eb75e1a..225980cb28a42 100644
--- a/llvm/include/llvm/Support/raw_socket_stream.h
+++ b/llvm/include/llvm/Support/raw_socket_stream.h
@@ -92,10 +92,11 @@ class ListeningSocket {
/// Accepts an incoming connection on the listening socket. This method can
/// optionally either block until a connection is available or timeout after a
/// specified amount of time has passed. By default the method will block
- /// until the socket has recieved a connection.
+ /// until the socket has recieved a connection. If the accept timesout this
+ /// method will return std::errc:timed_out
///
/// \param Timeout An optional timeout duration in milliseconds. Setting
- /// Timeout to -1 causes accept to block indefinitely
+ /// Timeout to a negative number causes ::accept to block indefinitely
///
Expected<std::unique_ptr<raw_socket_stream>>
accept(std::chrono::milliseconds Timeout = std::chrono::milliseconds(-1));
@@ -124,11 +125,25 @@ class raw_socket_stream : public raw_fd_stream {
public:
raw_socket_stream(int SocketFD);
+ ~raw_socket_stream();
+
/// Create a \p raw_socket_stream connected to the UNIX domain socket at \p
/// SocketPath.
static Expected<std::unique_ptr<raw_socket_stream>>
createConnectedUnix(StringRef SocketPath);
- ~raw_socket_stream();
+
+ /// Attempt to read from the raw_socket_stream's file descriptor. This method
+ /// can optionally either block until data is read or an error has occurred or
+ /// timeout after a specified amount of time has passed. By default the method
+ /// will block until the socket has read data or encountered an error. If the
+ /// read timesout this method will return std::errc:timed_out
+ ///
+ /// \param Timeout An optional timeout duration in milliseconds
+ /// \param Ptr The start of the buffer that will hold any read data
+ /// \param Size The number of bytes to be read
+ ///
+ Expected<std::string> readFromSocket(
+ std::chrono::milliseconds Timeout = std::chrono::milliseconds(-1));
};
} // end namespace llvm
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 76f148acf491b..cfc39ecd90c13 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -18,6 +18,7 @@
#include <atomic>
#include <fcntl.h>
+#include <functional>
#include <thread>
#ifndef _WIN32
@@ -177,18 +178,27 @@ Expected<ListeningSocket> ListeningSocket::createUnix(StringRef SocketPath,
#endif // _WIN32
}
-static llvm::Error manageTimeout(std::atomic<int> &ActiveFD, int CancelFD,
- std::chrono::milliseconds Timeout) {
+// If a file descriptor being monitored by poll is closed by another thread, the
+// result is unspecified. In the case poll does not unblock and return when
+// ActiveFD is closed you can provide another file descriptor via CancelFD that
+// when written to will cause poll to return
+static llvm::Error manageTimeout(std::chrono::milliseconds Timeout,
+ std::function<int()> getActiveFD,
+ std::optional<int> CancelFD = std::nullopt) {
struct pollfd FD[2];
FD[0].events = POLLIN;
#ifdef _WIN32
SOCKET WinServerSock = _get_osfhandle(FD);
FD[0].fd = WinServerSock;
#else
- FD[0].fd = ActiveFD.load();
+ FD[0].fd = getActiveFD();
#endif
- FD[1].events = POLLIN;
- FD[1].fd = CancelFD;
+ uint8_t FDCount = 1;
+ if (CancelFD.has_value()) {
+ FD[1].events = POLLIN;
+ FD[1].fd = CancelFD.value();
+ FDCount++;
+ }
// Keep track of how much time has passed in case ::poll or WSAPoll are
// interupted by a signal and need to be recalled
@@ -197,20 +207,19 @@ static llvm::Error manageTimeout(std::atomic<int> &ActiveFD, int CancelFD,
int PollStatus = -1;
while (PollStatus == -1 && (Timeout.count() == -1 || ElapsedTime < Timeout)) {
- // Timeout of -1 indicates that no Timeout was provided
if (Timeout.count() != -1)
RemainingTime -= ElapsedTime.count();
auto Start = std::chrono::steady_clock::now();
#ifdef _WIN32
- PollStatus = WSAPoll(FD, 2, RemainingTime);
+ PollStatus = WSAPoll(FD, FDCount, RemainingTime);
#else
- PollStatus = ::poll(FD, 2, RemainingTime);
+ PollStatus = ::poll(FD, FDCount, RemainingTime);
#endif
// If FD equals -1 then ListeningSocket::shutdown has been called and it is
// appropriate to return operation_canceled
- if (ActiveFD.load() == -1)
+ if (getActiveFD() == -1)
return llvm::make_error<StringError>(
std::make_error_code(std::errc::operation_canceled),
"Accept canceled");
@@ -242,13 +251,14 @@ static llvm::Error manageTimeout(std::atomic<int> &ActiveFD, int CancelFD,
Expected<std::unique_ptr<raw_socket_stream>>
ListeningSocket::accept(std::chrono::milliseconds Timeout) {
- llvm::Error TimeoutErr = manageTimeout(FD, PipeFD[0], Timeout);
+ auto getActiveFD = [this]() -> int { return FD; };
+ llvm::Error TimeoutErr = manageTimeout(Timeout, getActiveFD, PipeFD[0]);
if (TimeoutErr)
return TimeoutErr;
int AcceptFD;
#ifdef _WIN32
- SOCKET WinAcceptSock = ::accept(WinServerSock, NULL, NULL);
+ SOCKET WinAcceptSock = ::accept(_get_osfhandle(FD), NULL, NULL);
AcceptFD = _open_osfhandle(WinAcceptSock, 0);
#else
AcceptFD = ::accept(FD, NULL, NULL);
@@ -303,6 +313,8 @@ ListeningSocket::~ListeningSocket() {
raw_socket_stream::raw_socket_stream(int SocketFD)
: raw_fd_stream(SocketFD, true) {}
+raw_socket_stream::~raw_socket_stream() {}
+
Expected<std::unique_ptr<raw_socket_stream>>
raw_socket_stream::createConnectedUnix(StringRef SocketPath) {
#ifdef _WIN32
@@ -314,4 +326,30 @@ raw_socket_stream::createConnectedUnix(StringRef SocketPath) {
return std::make_unique<raw_socket_stream>(*FD);
}
-raw_socket_stream::~raw_socket_stream() {}
+Expected<std::string>
+raw_socket_stream::readFromSocket(std::chrono::milliseconds Timeout) {
+ auto getActiveFD = [this]() -> int { return this->get_fd(); };
+ llvm::Error TimeoutErr = manageTimeout(Timeout, getActiveFD);
+ if (TimeoutErr)
+ return TimeoutErr;
+
+ std::vector<char> Buffer;
+ constexpr ssize_t TmpBufferSize = 1024;
+ char TmpBuffer[TmpBufferSize];
+
+ while (true) {
+ std::memset(TmpBuffer, 0, TmpBufferSize);
+ ssize_t BytesRead = this->read(TmpBuffer, TmpBufferSize);
+ if (BytesRead == -1)
+ return llvm::make_error<StringError>(this->error(), "read failed");
+ else if (BytesRead == 0)
+ break;
+ else
+ Buffer.insert(Buffer.end(), TmpBuffer, TmpBuffer + BytesRead);
+ // All available bytes have been read. Another call to read will block
+ if (BytesRead < TmpBufferSize)
+ break;
+ }
+
+ return std::string(Buffer.begin(), Buffer.end());
+}
diff --git a/llvm/unittests/Support/raw_socket_stream_test.cpp b/llvm/unittests/Support/raw_socket_stream_test.cpp
index c4e8cfbbe7e6a..1b8f85f88f1af 100644
--- a/llvm/unittests/Support/raw_socket_stream_test.cpp
+++ b/llvm/unittests/Support/raw_socket_stream_test.cpp
@@ -58,21 +58,106 @@ TEST(raw_socket_streamTest, CLIENT_TO_SERVER_AND_SERVER_TO_CLIENT) {
Client << "01234567";
Client.flush();
- char Bytes[8];
- ssize_t BytesRead = Server.read(Bytes, 8);
+ llvm::Expected<std::string> MaybeText = Server.readFromSocket();
+ ASSERT_THAT_EXPECTED(MaybeText, llvm::Succeeded());
+ ASSERT_EQ("01234567", *MaybeText);
+}
+
+TEST(raw_socket_streamTest, LARGE_READ) {
+ if (!hasUnixSocketSupport())
+ GTEST_SKIP();
+
+ SmallString<100> SocketPath;
+ llvm::sys::fs::createUniquePath("large_read.sock", SocketPath, true);
+
+ // Make sure socket file does not exist. May still be there from the last test
+ std::remove(SocketPath.c_str());
+
+ Expected<ListeningSocket> MaybeServerListener =
+ ListeningSocket::createUnix(SocketPath);
+ ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded());
+ ListeningSocket ServerListener = std::move(*MaybeServerListener);
+
+ Expected<std::unique_ptr<raw_socket_stream>> MaybeClient =
+ raw_socket_stream::createConnectedUnix(SocketPath);
+ ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded());
+ raw_socket_stream &Client = **MaybeClient;
+
+ Expected<std::unique_ptr<raw_socket_stream>> MaybeServer =
+ ServerListener.accept();
+ ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded());
+ raw_socket_stream &Server = **MaybeServer;
+
+ // raw_socket_stream::readFromSocket pre-allocates a buffer 1024 bytes large.
+ // Test to make sure readFromSocket can handle messages larger then size of
+ // pre-allocated block
+ constexpr int TextLength = 1342;
+ constexpr char Text[TextLength] =
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
+ "eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel orci "
+ "porta non pulvinar neque laoreet suspendisse interdum consectetur. "
+ "Nulla facilisi etiam dignissim diam quis. Porttitor massa id neque "
+ "aliquam vestibulum morbi blandit cursus. Purus viverra accumsan in "
+ "nisl. Nunc non blandit massa enim nec dui nunc mattis enim. Rhoncus "
+ "dolor purus non enim praesent elementum facilisis leo. Parturient "
+ "montes nascetur ridiculus mus mauris. Urna condimentum mattis "
+ "pellentesque id nibh tortor id aliquet lectus. Orci eu lobortis "
+ "elementum nibh. Sagittis eu volutpat odio facilisis. Molestie a "
+ "iaculis at erat pellentesque adipiscing. Tincidunt augue interdum "
+ "velit euismod in pellentesque massa placerat. Cras ornare arcu dui "
+ "vivamus arcu felis bibendum ut tristique. Tellus elementum sagittis "
+ "vitae et leo duis. Scelerisque fermentum dui faucibus in ornare "
+ "quam. Ipsum a arcu cursus vitae congue. Sit amet nisl suscipit "
+ "adipiscing. Sociis natoque penatibus et magnis. Cras semper auctor "
+ "neque vitae tempus quam pellentesque. Neque gravida in fermentum et "
+ "sollicitudin ac orci phasellus egestas. Vitae suscipit tellus mauris "
+ "a diam maecenas sed. Lectus arcu bibendum at varius vel pharetra. "
+ "Dignissim sodales ut eu sem integer vitae justo. Id cursus metus "
+ "aliquam eleifend mi.";
+ Client << Text;
+ Client.flush();
+
+ llvm::Expected<std::string> MaybeText = Server.readFromSocket();
+ ASSERT_THAT_EXPECTED(MaybeText, llvm::Succeeded());
+ ASSERT_EQ(Text, *MaybeText);
+}
- std::string string(Bytes, 8);
+TEST(raw_socket_streamTest, READ_WITH_TIMEOUT) {
+ if (!hasUnixSocketSupport())
+ GTEST_SKIP();
+
+ SmallString<100> SocketPath;
+ llvm::sys::fs::createUniquePath("read_with_timeout.sock", SocketPath, true);
- ASSERT_EQ(8, BytesRead);
- ASSERT_EQ("01234567", string);
+ // Make sure socket file does not exist. May still be there from the last test
+ std::remove(SocketPath.c_str());
+
+ Expected<ListeningSocket> MaybeServerListener =
+ ListeningSocket::createUnix(SocketPath);
+ ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded());
+ ListeningSocket ServerListener = std::move(*MaybeServerListener);
+
+ Expected<std::unique_ptr<raw_socket_stream>> MaybeClient =
+ raw_socket_stream::createConnectedUnix(SocketPath);
+ ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded());
+
+ Expected<std::unique_ptr<raw_socket_stream>> MaybeServer =
+ ServerListener.accept();
+ ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded());
+ raw_socket_stream &Server = **MaybeServer;
+
+ llvm::Expected<std::string> MaybeBytesRead =
+ Server.readFromSocket(std::chrono::milliseconds(100));
+ ASSERT_EQ(llvm::errorToErrorCode(MaybeBytesRead.takeError()),
+ std::errc::timed_out);
}
-TEST(raw_socket_streamTest, TIMEOUT_PROVIDED) {
+TEST(raw_socket_streamTest, ACCEPT_WITH_TIMEOUT) {
if (!hasUnixSocketSupport())
GTEST_SKIP();
SmallString<100> SocketPath;
- llvm::sys::fs::createUniquePath("timout_provided.sock", SocketPath, true);
+ llvm::sys::fs::createUniquePath("accept_with_timeout.sock", SocketPath, true);
// Make sure socket file does not exist. May still be there from the last test
std::remove(SocketPath.c_str());
@@ -82,19 +167,19 @@ TEST(raw_socket_streamTest, TIMEOUT_PROVIDED) {
ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded());
ListeningSocket ServerListener = std::move(*MaybeServerListener);
- std::chrono::milliseconds Timeout = std::chrono::milliseconds(100);
Expected<std::unique_ptr<raw_socket_stream>> MaybeServer =
- ServerListener.accept(Timeout);
+ ServerListener.accept(std::chrono::milliseconds(100));
ASSERT_EQ(llvm::errorToErrorCode(MaybeServer.takeError()),
std::errc::timed_out);
}
-TEST(raw_socket_streamTest, FILE_DESCRIPTOR_CLOSED) {
+TEST(raw_socket_streamTest, ACCEPT_WITH_SHUTDOWN) {
if (!hasUnixSocketSupport())
GTEST_SKIP();
SmallString<100> SocketPath;
- llvm::sys::fs::createUniquePath("fd_closed.sock", SocketPath, true);
+ llvm::sys::fs::createUniquePath("accept_with_shutdown.sock", SocketPath,
+ true);
// Make sure socket file does not exist. May still be there from the last test
std::remove(SocketPath.c_str());
>From a31daa2fd626dbcb598258140ccf4fa92e2bad58 Mon Sep 17 00:00:00 2001
From: cpsughrue <cpsughrue at gmail.com>
Date: Sun, 2 Jun 2024 22:22:04 -0400
Subject: [PATCH 5/7] Include check to see if CloseFD has been written to
---
llvm/lib/Support/raw_socket_stream.cpp | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index cfc39ecd90c13..1cd70c95bd4de 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -181,7 +181,8 @@ Expected<ListeningSocket> ListeningSocket::createUnix(StringRef SocketPath,
// If a file descriptor being monitored by poll is closed by another thread, the
// result is unspecified. In the case poll does not unblock and return when
// ActiveFD is closed you can provide another file descriptor via CancelFD that
-// when written to will cause poll to return
+// when written to will cause poll to return. Typically CancelFD is the read end
+// of a unidirectional pipe.
static llvm::Error manageTimeout(std::chrono::milliseconds Timeout,
std::function<int()> getActiveFD,
std::optional<int> CancelFD = std::nullopt) {
@@ -217,9 +218,9 @@ static llvm::Error manageTimeout(std::chrono::milliseconds Timeout,
PollStatus = ::poll(FD, FDCount, RemainingTime);
#endif
- // If FD equals -1 then ListeningSocket::shutdown has been called and it is
- // appropriate to return operation_canceled
- if (getActiveFD() == -1)
+ // If ActiveFD equals -1 or CancelFD has data to be read then the operation
+ // has been canceled by another thread
+ if (getActiveFD() == -1 || FD[1].revents & POLLIN)
return llvm::make_error<StringError>(
std::make_error_code(std::errc::operation_canceled),
"Accept canceled");
>From 4bb12e41be0f7ebfd1c81ef3abbb24e9981f81da Mon Sep 17 00:00:00 2001
From: cpsughrue <cpsughrue at gmail.com>
Date: Sun, 2 Jun 2024 22:53:33 -0400
Subject: [PATCH 6/7] Fix type passed to _get_osfhandle
---
llvm/lib/Support/raw_socket_stream.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 1cd70c95bd4de..063f6fc366da9 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -189,7 +189,7 @@ static llvm::Error manageTimeout(std::chrono::milliseconds Timeout,
struct pollfd FD[2];
FD[0].events = POLLIN;
#ifdef _WIN32
- SOCKET WinServerSock = _get_osfhandle(FD);
+ SOCKET WinServerSock = _get_osfhandle(getActiveFD());
FD[0].fd = WinServerSock;
#else
FD[0].fd = getActiveFD();
>From 83b8a820ce2979390180688f1a3e8c4fc74ee50a Mon Sep 17 00:00:00 2001
From: cpsughrue <cpsughrue at gmail.com>
Date: Mon, 17 Jun 2024 16:50:37 -0400
Subject: [PATCH 7/7] Reimplement raw_socket_stream::read as an override or
raw_fs_stream::read
---
llvm/include/llvm/Support/raw_socket_stream.h | 19 ++---
llvm/lib/Support/raw_socket_stream.cpp | 26 ++-----
.../Support/raw_socket_stream_test.cpp | 71 +++----------------
3 files changed, 24 insertions(+), 92 deletions(-)
diff --git a/llvm/include/llvm/Support/raw_socket_stream.h b/llvm/include/llvm/Support/raw_socket_stream.h
index 225980cb28a42..2fb2fab570599 100644
--- a/llvm/include/llvm/Support/raw_socket_stream.h
+++ b/llvm/include/llvm/Support/raw_socket_stream.h
@@ -132,18 +132,21 @@ class raw_socket_stream : public raw_fd_stream {
static Expected<std::unique_ptr<raw_socket_stream>>
createConnectedUnix(StringRef SocketPath);
- /// Attempt to read from the raw_socket_stream's file descriptor. This method
- /// can optionally either block until data is read or an error has occurred or
- /// timeout after a specified amount of time has passed. By default the method
- /// will block until the socket has read data or encountered an error. If the
- /// read timesout this method will return std::errc:timed_out
+ /// Attempt to read from the raw_socket_stream's file descriptor.
+ ///
+ /// This method can optionally either block until data is read or an error has
+ /// occurred or timeout after a specified amount of time has passed. By
+ /// default the method will block until the socket has read data or
+ /// encountered an error. If the read times out this method will return
+ /// std::errc:timed_out
///
- /// \param Timeout An optional timeout duration in milliseconds
/// \param Ptr The start of the buffer that will hold any read data
/// \param Size The number of bytes to be read
+ /// \param Timeout An optional timeout duration in milliseconds
///
- Expected<std::string> readFromSocket(
- std::chrono::milliseconds Timeout = std::chrono::milliseconds(-1));
+ llvm::Expected<ssize_t>
+ read(char *Ptr, size_t Size,
+ std::chrono::milliseconds Timeout = std::chrono::milliseconds(-1));
};
} // end namespace llvm
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 063f6fc366da9..5af0f308cc141 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -327,30 +327,12 @@ raw_socket_stream::createConnectedUnix(StringRef SocketPath) {
return std::make_unique<raw_socket_stream>(*FD);
}
-Expected<std::string>
-raw_socket_stream::readFromSocket(std::chrono::milliseconds Timeout) {
+llvm::Expected<ssize_t>
+raw_socket_stream::read(char *Ptr, size_t Size,
+ std::chrono::milliseconds Timeout) {
auto getActiveFD = [this]() -> int { return this->get_fd(); };
llvm::Error TimeoutErr = manageTimeout(Timeout, getActiveFD);
if (TimeoutErr)
return TimeoutErr;
-
- std::vector<char> Buffer;
- constexpr ssize_t TmpBufferSize = 1024;
- char TmpBuffer[TmpBufferSize];
-
- while (true) {
- std::memset(TmpBuffer, 0, TmpBufferSize);
- ssize_t BytesRead = this->read(TmpBuffer, TmpBufferSize);
- if (BytesRead == -1)
- return llvm::make_error<StringError>(this->error(), "read failed");
- else if (BytesRead == 0)
- break;
- else
- Buffer.insert(Buffer.end(), TmpBuffer, TmpBuffer + BytesRead);
- // All available bytes have been read. Another call to read will block
- if (BytesRead < TmpBufferSize)
- break;
- }
-
- return std::string(Buffer.begin(), Buffer.end());
+ return raw_fd_stream::read(Ptr, Size);
}
diff --git a/llvm/unittests/Support/raw_socket_stream_test.cpp b/llvm/unittests/Support/raw_socket_stream_test.cpp
index 1b8f85f88f1af..fcbabad86a6f0 100644
--- a/llvm/unittests/Support/raw_socket_stream_test.cpp
+++ b/llvm/unittests/Support/raw_socket_stream_test.cpp
@@ -58,68 +58,14 @@ TEST(raw_socket_streamTest, CLIENT_TO_SERVER_AND_SERVER_TO_CLIENT) {
Client << "01234567";
Client.flush();
- llvm::Expected<std::string> MaybeText = Server.readFromSocket();
- ASSERT_THAT_EXPECTED(MaybeText, llvm::Succeeded());
- ASSERT_EQ("01234567", *MaybeText);
-}
-
-TEST(raw_socket_streamTest, LARGE_READ) {
- if (!hasUnixSocketSupport())
- GTEST_SKIP();
+ char Bytes[8];
+ llvm::Expected<ssize_t> MaybeBytesRead = Server.read(Bytes, 8);
+ ASSERT_THAT_EXPECTED(MaybeBytesRead, llvm::Succeeded());
- SmallString<100> SocketPath;
- llvm::sys::fs::createUniquePath("large_read.sock", SocketPath, true);
-
- // Make sure socket file does not exist. May still be there from the last test
- std::remove(SocketPath.c_str());
-
- Expected<ListeningSocket> MaybeServerListener =
- ListeningSocket::createUnix(SocketPath);
- ASSERT_THAT_EXPECTED(MaybeServerListener, llvm::Succeeded());
- ListeningSocket ServerListener = std::move(*MaybeServerListener);
-
- Expected<std::unique_ptr<raw_socket_stream>> MaybeClient =
- raw_socket_stream::createConnectedUnix(SocketPath);
- ASSERT_THAT_EXPECTED(MaybeClient, llvm::Succeeded());
- raw_socket_stream &Client = **MaybeClient;
-
- Expected<std::unique_ptr<raw_socket_stream>> MaybeServer =
- ServerListener.accept();
- ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded());
- raw_socket_stream &Server = **MaybeServer;
-
- // raw_socket_stream::readFromSocket pre-allocates a buffer 1024 bytes large.
- // Test to make sure readFromSocket can handle messages larger then size of
- // pre-allocated block
- constexpr int TextLength = 1342;
- constexpr char Text[TextLength] =
- "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
- "eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel orci "
- "porta non pulvinar neque laoreet suspendisse interdum consectetur. "
- "Nulla facilisi etiam dignissim diam quis. Porttitor massa id neque "
- "aliquam vestibulum morbi blandit cursus. Purus viverra accumsan in "
- "nisl. Nunc non blandit massa enim nec dui nunc mattis enim. Rhoncus "
- "dolor purus non enim praesent elementum facilisis leo. Parturient "
- "montes nascetur ridiculus mus mauris. Urna condimentum mattis "
- "pellentesque id nibh tortor id aliquet lectus. Orci eu lobortis "
- "elementum nibh. Sagittis eu volutpat odio facilisis. Molestie a "
- "iaculis at erat pellentesque adipiscing. Tincidunt augue interdum "
- "velit euismod in pellentesque massa placerat. Cras ornare arcu dui "
- "vivamus arcu felis bibendum ut tristique. Tellus elementum sagittis "
- "vitae et leo duis. Scelerisque fermentum dui faucibus in ornare "
- "quam. Ipsum a arcu cursus vitae congue. Sit amet nisl suscipit "
- "adipiscing. Sociis natoque penatibus et magnis. Cras semper auctor "
- "neque vitae tempus quam pellentesque. Neque gravida in fermentum et "
- "sollicitudin ac orci phasellus egestas. Vitae suscipit tellus mauris "
- "a diam maecenas sed. Lectus arcu bibendum at varius vel pharetra. "
- "Dignissim sodales ut eu sem integer vitae justo. Id cursus metus "
- "aliquam eleifend mi.";
- Client << Text;
- Client.flush();
+ std::string String(Bytes, 8);
- llvm::Expected<std::string> MaybeText = Server.readFromSocket();
- ASSERT_THAT_EXPECTED(MaybeText, llvm::Succeeded());
- ASSERT_EQ(Text, *MaybeText);
+ ASSERT_EQ(8, *MaybeBytesRead);
+ ASSERT_EQ("01234567", String);
}
TEST(raw_socket_streamTest, READ_WITH_TIMEOUT) {
@@ -146,8 +92,9 @@ TEST(raw_socket_streamTest, READ_WITH_TIMEOUT) {
ASSERT_THAT_EXPECTED(MaybeServer, llvm::Succeeded());
raw_socket_stream &Server = **MaybeServer;
- llvm::Expected<std::string> MaybeBytesRead =
- Server.readFromSocket(std::chrono::milliseconds(100));
+ char Bytes[8];
+ llvm::Expected<ssize_t> MaybeBytesRead =
+ Server.read(Bytes, 8, std::chrono::milliseconds(100));
ASSERT_EQ(llvm::errorToErrorCode(MaybeBytesRead.takeError()),
std::errc::timed_out);
}
More information about the llvm-commits
mailing list