Skip to content

Commit 0520fd9

Browse files
committed
Fix some windows build issues
1 parent a55d698 commit 0520fd9

File tree

2 files changed

+59
-43
lines changed

2 files changed

+59
-43
lines changed

llvm/include/llvm/Support/raw_socket_stream.h

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,16 @@ class WSABalancer {
5959
///
6060
class ListeningSocket {
6161

62-
/// If ListeningSocket::shutdown is used by a signal handler to clean up
63-
/// ListeningSocket resources FD may be closed while ::poll is waiting for
64-
/// FD to become ready to perform I/O. When FD is closed ::poll will
65-
/// continue to block so use the self-pipe trick to get ::poll to return
66-
int PipeFD[2];
67-
std::mutex PipeMutex;
6862
std::atomic<int> FD;
69-
std::string SocketPath; // Never modified
70-
ListeningSocket(int SocketFD, StringRef SocketPath);
63+
std::string SocketPath; // Never modified after construction
64+
65+
/// If a seperate thread calls ListeningSocket::shutdown, the ListeningSocket
66+
/// file descriptor (FD) could be closed while ::poll is waiting for it to be
67+
/// ready to performa I/O operations. ::poll with continue to block even after
68+
/// FD is closed so use a self-pipe mechanism to get ::poll to return
69+
int PipeFD[2]; // Never modified after construction
70+
71+
ListeningSocket(int SocketFD, StringRef SocketPath, int PipeFD[2]);
7172

7273
#ifdef _WIN32
7374
WSABalancer _;
@@ -79,14 +80,20 @@ class ListeningSocket {
7980
ListeningSocket(const ListeningSocket &LS) = delete;
8081
ListeningSocket &operator=(const ListeningSocket &) = delete;
8182

82-
/// Closes the socket's FD and unlinks the socket file from the file system.
83-
/// The method is thread and signal safe
83+
/// Closes the FD, unlinks the socket file, and writes to PipeFD.
84+
///
85+
/// After the construction of the ListeningSocket, shutdown is signal safe if
86+
/// it is called during the lifetime of the object. shutdown can be called
87+
/// concurrently with ListeningSocket::accept as writing to PipeFD will cause
88+
/// a blocking call to ::poll to return.
89+
///
90+
/// Once shutdown is called there is no way to reinitialize ListeningSocket.
8491
void shutdown();
8592

8693
/// Accepts an incoming connection on the listening socket. This method can
8794
/// optionally either block until a connection is available or timeout after a
8895
/// specified amount of time has passed. By default the method will block
89-
/// until the socket has recieved a connection
96+
/// until the socket has recieved a connection.
9097
///
9198
/// \param Timeout An optional timeout duration in milliseconds
9299
///

llvm/lib/Support/raw_socket_stream.cpp

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,36 +71,40 @@ static sockaddr_un setSocketAddr(StringRef SocketPath) {
7171

7272
static Expected<int> getSocketFD(StringRef SocketPath) {
7373
#ifdef _WIN32
74-
SOCKET MaybeSocket = socket(AF_UNIX, SOCK_STREAM, 0);
75-
if (MaybeSocket == INVALID_SOCKET) {
74+
SOCKET Socket = socket(AF_UNIX, SOCK_STREAM, 0);
75+
if (Socket == INVALID_SOCKET) {
7676
#else
77-
int MaybeSocket = socket(AF_UNIX, SOCK_STREAM, 0);
78-
if (MaybeSocket == -1) {
77+
int Socket = socket(AF_UNIX, SOCK_STREAM, 0);
78+
if (Socket == -1) {
7979
#endif // _WIN32
8080
return llvm::make_error<StringError>(getLastSocketErrorCode(),
8181
"Create socket failed");
8282
}
8383

8484
struct sockaddr_un Addr = setSocketAddr(SocketPath);
85-
if (::connect(MaybeSocket, (struct sockaddr *)&Addr, sizeof(Addr)) == -1)
85+
if (::connect(Socket, (struct sockaddr *)&Addr, sizeof(Addr)) == -1)
8686
return llvm::make_error<StringError>(getLastSocketErrorCode(),
8787
"Connect socket failed");
8888

8989
#ifdef _WIN32
90-
return _open_osfhandle(MaybeWinsocket, 0);
90+
return _open_osfhandle(Socket, 0);
9191
#else
92-
return MaybeSocket;
92+
return Socket;
9393
#endif // _WIN32
9494
}
9595

96-
ListeningSocket::ListeningSocket(int SocketFD, StringRef SocketPath)
97-
: FD(SocketFD), SocketPath(SocketPath) {}
96+
ListeningSocket::ListeningSocket(int SocketFD, StringRef SocketPath,
97+
int PipeFD[2])
98+
: FD(SocketFD), SocketPath(SocketPath), PipeFD{PipeFD[0], PipeFD[1]} {}
9899

99100
ListeningSocket::ListeningSocket(ListeningSocket &&LS)
100-
: FD(LS.FD.load()), SocketPath(LS.SocketPath) {
101+
: FD(LS.FD.load()),
102+
SocketPath(LS.SocketPath), PipeFD{LS.PipeFD[0], LS.PipeFD[1]} {
101103

102-
LS.SocketPath.clear();
103104
LS.FD = -1;
105+
LS.SocketPath.clear();
106+
LS.PipeFD[0] = -1;
107+
LS.PipeFD[1] = -1;
104108
}
105109

106110
Expected<ListeningSocket>
@@ -135,36 +139,38 @@ ListeningSocket::createListeningUnixSocket(StringRef SocketPath,
135139

136140
#ifdef _WIN32
137141
WSABalancer _;
138-
SOCKET MaybeSocket = socket(AF_UNIX, SOCK_STREAM, 0);
139-
if (MaybeSocket == INVALID_SOCKET) {
142+
SOCKET Socket = socket(AF_UNIX, SOCK_STREAM, 0);
143+
if (Socket == INVALID_SOCKET) {
140144
#else
141-
int MaybeSocket = socket(AF_UNIX, SOCK_STREAM, 0);
142-
if (MaybeSocket == -1) {
145+
int Socket = socket(AF_UNIX, SOCK_STREAM, 0);
146+
if (Socket == -1)
143147
#endif
144148
return llvm::make_error<StringError>(getLastSocketErrorCode(),
145149
"socket create failed");
146-
}
147150

148151
struct sockaddr_un Addr = setSocketAddr(SocketPath);
149-
if (::bind(MaybeSocket, (struct sockaddr *)&Addr, sizeof(Addr)) == -1) {
152+
if (::bind(Socket, (struct sockaddr *)&Addr, sizeof(Addr)) == -1) {
150153
// Grab error code from call to ::bind before calling ::close
151154
std::error_code EC = getLastSocketErrorCode();
152-
::close(MaybeSocket);
155+
::close(Socket);
153156
return llvm::make_error<StringError>(EC, "Bind error");
154157
}
155158

156159
// Mark socket as passive so incoming connections can be accepted
157-
if (::listen(MaybeSocket, MaxBacklog) == -1)
160+
if (::listen(Socket, MaxBacklog) == -1)
158161
return llvm::make_error<StringError>(getLastSocketErrorCode(),
159162
"Listen error");
160163

161-
int Socket;
164+
int PipeFD[2];
165+
if (::pipe(PipeFD) == -1)
166+
return llvm::make_error<StringError>(getLastSocketErrorCode(),
167+
"pipe failed");
168+
162169
#ifdef _WIN32
163-
Socket = _open_osfhandle(MaybeWinsocket, 0);
170+
return ListeningSocket{_open_osfhandle(Socket, 0), SocketPath, PipeFD};
164171
#else
165-
Socket = MaybeSocket;
172+
return ListeningSocket{Socket, SocketPath, PipeFD};
166173
#endif // _WIN32
167-
return ListeningSocket{Socket, SocketPath};
168174
}
169175

170176
Expected<std::unique_ptr<raw_socket_stream>>
@@ -180,12 +186,7 @@ ListeningSocket::accept(std::optional<std::chrono::milliseconds> Timeout) {
180186
#endif
181187

182188
FDs[1].events = POLLIN;
183-
PipeMutex.lock();
184-
if (::pipe(PipeFD) == -1)
185-
return llvm::make_error<StringError>(getLastSocketErrorCode(),
186-
"pipe failed");
187189
FDs[1].fd = PipeFD[0];
188-
PipeMutex.unlock();
189190

190191
int TimeoutCount = Timeout.value_or(std::chrono::milliseconds(-1)).count();
191192
int PollStatus = ::poll(FDs, 2, TimeoutCount);
@@ -223,14 +224,22 @@ void ListeningSocket::shutdown() {
223224
::close(FD);
224225
::unlink(SocketPath.c_str());
225226

227+
// Ensure ::poll returns if shutdown is called by a seperate thread
226228
char Byte = 'A';
227-
PipeMutex.lock();
228-
write(PipeFD[1], &Byte, 1);
229-
PipeMutex.unlock();
229+
::write(PipeFD[1], &Byte, 1);
230+
230231
FD = -1;
231232
}
232233

233-
ListeningSocket::~ListeningSocket() { shutdown(); }
234+
ListeningSocket::~ListeningSocket() {
235+
shutdown();
236+
237+
// Close the pipe's FDs in the destructor instead of within
238+
// ListeningSocket::shutdown to avoid unnecessary synchronization issues that
239+
// would occur as PipeFD's values would have to be changed to -1
240+
::close(PipeFD[0]);
241+
::close(PipeFD[1]);
242+
}
234243

235244
//===----------------------------------------------------------------------===//
236245
// raw_socket_stream

0 commit comments

Comments
 (0)