in tensorpipe/transport/uv/utility.cc [53:136]
std::tuple<Error, std::string> lookupAddrForHostname() {
// For some operations we need a libuv event loop. We create a fresh one, just
// for this purpose, which we'll drive inline from this thread. This way we
// avoid misusing the main event loop in the context impl.
struct InlineLoop {
uv_loop_t loop;
InlineLoop() {
auto rv = uv_loop_init(&loop);
TP_THROW_UV_IF(rv < 0, rv);
}
~InlineLoop() {
auto rv = uv_loop_close(&loop);
TP_THROW_UV_IF(rv < 0, rv);
}
};
InlineLoop loop;
struct InlineDeferredExecutor : public DeferredExecutor {
std::thread::id threadId = std::this_thread::get_id();
void deferToLoop(TTask fn) override {
TP_THROW_ASSERT()
<< "How could this be called?! This class is supposed to be "
<< "instantiated as const, and this method isn't const-qualified";
}
bool inLoop() const override {
return std::this_thread::get_id() == threadId;
}
};
const InlineDeferredExecutor executor;
int rv;
std::string hostname;
std::tie(rv, hostname) = getHostname();
if (rv < 0) {
return std::make_tuple(TP_CREATE_ERROR(UVError, rv), std::string());
}
Addrinfo info;
std::tie(rv, info) = getAddrinfoFromLoop(&loop.loop, std::move(hostname));
if (rv < 0) {
return std::make_tuple(TP_CREATE_ERROR(UVError, rv), std::string());
}
Error error;
for (struct addrinfo* rp = info.get(); rp != nullptr; rp = rp->ai_next) {
TP_DCHECK(rp->ai_family == AF_INET || rp->ai_family == AF_INET6);
TP_DCHECK_EQ(rp->ai_socktype, SOCK_STREAM);
TP_DCHECK_EQ(rp->ai_protocol, IPPROTO_TCP);
Sockaddr addr = Sockaddr(rp->ai_addr, rp->ai_addrlen);
TCPHandle handle(&loop.loop, executor);
handle.initFromLoop();
rv = handle.bindFromLoop(addr);
handle.closeFromLoop();
// The handle will only be closed at the next loop iteration, so run it.
{
auto rv = uv_run(&loop.loop, UV_RUN_DEFAULT);
TP_THROW_ASSERT_IF(rv > 0);
}
if (rv < 0) {
// Record the first binding error we encounter and return that in the end
// if no working address is found, in order to help with debugging.
if (!error) {
error = TP_CREATE_ERROR(UVError, rv);
}
continue;
}
return std::make_tuple(Error::kSuccess, addr.str());
}
if (error) {
return std::make_tuple(std::move(error), std::string());
} else {
return std::make_tuple(TP_CREATE_ERROR(NoAddrFoundError), std::string());
}
}