Commit bd05ffe8 authored by Kenton Varda's avatar Kenton Varda

Fix multiple problems with connect() on non-glibc-Linux:

1. Correctly set nonblocking flag *before* calling connect(). (On glibc-Linux, we create the socket already in nonblocking mode, so this was never an issue.)
2. FDs could be leaked if connect fails. (This applies to glibc-Linux too, although connect() would have to fail immediately without blocking, which is unusual.)
parent 572c689d
......@@ -1084,6 +1084,10 @@ public:
}
Promise<Own<AsyncIoStream>> wrapConnectingSocketFd(
int fd, const struct sockaddr* addr, uint addrlen, uint flags = 0) override {
// It's important that we construct the AsyncStreamFd first, so that `flags` are honored,
// especially setting nonblocking mode and taking ownership.
auto result = heap<AsyncStreamFd>(eventPort, fd, flags);
// Unfortunately connect() doesn't fit the mold of KJ_NONBLOCKING_SYSCALL, since it indicates
// non-blocking using EINPROGRESS.
for (;;) {
......@@ -1102,8 +1106,6 @@ public:
}
}
auto result = heap<AsyncStreamFd>(eventPort, fd, flags);
auto connected = result->waitConnected();
return connected.then(kj::mvCapture(result, [fd](Own<AsyncIoStream>&& stream) {
int err;
......@@ -1223,12 +1225,11 @@ private:
ArrayPtr<SocketAddress> addrs) {
KJ_ASSERT(addrs.size() > 0);
int fd = addrs[0].socket(SOCK_STREAM);
return kj::evalNow([&]() -> Promise<Own<AsyncIoStream>> {
if (!addrs[0].allowedBy(filter)) {
return KJ_EXCEPTION(FAILED, "connect() blocked by restrictPeers()");
} else {
int fd = addrs[0].socket(SOCK_STREAM);
return lowLevel.wrapConnectingSocketFd(
fd, addrs[0].getRaw(), addrs[0].getRawSize(), NEW_FD_FLAGS);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment