HDFS-10310. hdfsConnect hangs when given bad host or port. Contributed by James Clampffer.
This commit is contained in:
parent
e542db66ee
commit
cc51f2ce58
|
@ -82,6 +82,34 @@ bool lock_held(T & mutex) {
|
||||||
// Returns a string containing error message on failure, otherwise an empty string.
|
// Returns a string containing error message on failure, otherwise an empty string.
|
||||||
std::string SafeDisconnect(asio::ip::tcp::socket *sock);
|
std::string SafeDisconnect(asio::ip::tcp::socket *sock);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The following helper function is used for classes that look like the following:
|
||||||
|
//
|
||||||
|
// template <typename socket_like_object>
|
||||||
|
// class ObjectThatHoldsSocket {
|
||||||
|
// socket_like_object sock_;
|
||||||
|
// void DoSomethingWithAsioTcpSocket();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The trick here is that ObjectThatHoldsSocket may be templated on a mock socket
|
||||||
|
// in mock tests. If you have a method that explicitly needs to call some asio
|
||||||
|
// method unrelated to the mock test you need a way of making sure socket_like_object
|
||||||
|
// is, in fact, an asio::ip::tcp::socket. Otherwise the mocks need to implement
|
||||||
|
// lots of no-op boilerplate. This will return the value of the input param if
|
||||||
|
// it's a asio socket, and nullptr if it's anything else.
|
||||||
|
|
||||||
|
template <typename sock_t>
|
||||||
|
inline asio::ip::tcp::socket *get_asio_socket_ptr(sock_t *s) {
|
||||||
|
(void)s;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
template<>
|
||||||
|
inline asio::ip::tcp::socket *get_asio_socket_ptr<asio::ip::tcp::socket>
|
||||||
|
(asio::ip::tcp::socket *s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -56,8 +56,13 @@ void DataNodeConnectionImpl::Connect(
|
||||||
}
|
}
|
||||||
|
|
||||||
void DataNodeConnectionImpl::Cancel() {
|
void DataNodeConnectionImpl::Cancel() {
|
||||||
mutex_guard state_lock(state_lock_);
|
std::string err;
|
||||||
std::string err = SafeDisconnect(conn_.get());
|
|
||||||
|
{ // scope the lock for disconnect only, log has it's own lock
|
||||||
|
mutex_guard state_lock(state_lock_);
|
||||||
|
err = SafeDisconnect(conn_.get());
|
||||||
|
}
|
||||||
|
|
||||||
if(!err.empty()) {
|
if(!err.empty()) {
|
||||||
LOG_WARN(kBlockReader, << "Error disconnecting socket in DataNodeConnectionImpl::Cancel, " << err);
|
LOG_WARN(kBlockReader, << "Error disconnecting socket in DataNodeConnectionImpl::Cancel, " << err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,11 @@ void RpcConnectionImpl<NextLayer>::ConnectComplete(const ::asio::error_code &ec)
|
||||||
HandshakeComplete(s);
|
HandshakeComplete(s);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
next_layer_.close();
|
std::string err = SafeDisconnect(get_asio_socket_ptr(&next_layer_));
|
||||||
|
if(!err.empty()) {
|
||||||
|
LOG_INFO(kRPC, << "Rpc connection failed to connect to endpoint, error closing connection: " << err);
|
||||||
|
}
|
||||||
|
|
||||||
if (!additional_endpoints_.empty()) {
|
if (!additional_endpoints_.empty()) {
|
||||||
// If we have additional endpoints, keep trying until we either run out or
|
// If we have additional endpoints, keep trying until we either run out or
|
||||||
// hit one
|
// hit one
|
||||||
|
@ -355,8 +359,8 @@ void RpcConnectionImpl<NextLayer>::Disconnect() {
|
||||||
|
|
||||||
request_over_the_wire_.reset();
|
request_over_the_wire_.reset();
|
||||||
if (connected_ == kConnecting || connected_ == kConnected) {
|
if (connected_ == kConnecting || connected_ == kConnected) {
|
||||||
next_layer_.cancel();
|
// Don't print out errors, we were expecting a disconnect here
|
||||||
next_layer_.close();
|
SafeDisconnect(get_asio_socket_ptr(&next_layer_));
|
||||||
}
|
}
|
||||||
connected_ = kDisconnected;
|
connected_ = kDisconnected;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue