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.
|
||||
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
|
||||
|
|
|
@ -56,8 +56,13 @@ void DataNodeConnectionImpl::Connect(
|
|||
}
|
||||
|
||||
void DataNodeConnectionImpl::Cancel() {
|
||||
mutex_guard state_lock(state_lock_);
|
||||
std::string err = SafeDisconnect(conn_.get());
|
||||
std::string err;
|
||||
|
||||
{ // 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()) {
|
||||
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);
|
||||
});
|
||||
} 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 we have additional endpoints, keep trying until we either run out or
|
||||
// hit one
|
||||
|
@ -355,8 +359,8 @@ void RpcConnectionImpl<NextLayer>::Disconnect() {
|
|||
|
||||
request_over_the_wire_.reset();
|
||||
if (connected_ == kConnecting || connected_ == kConnected) {
|
||||
next_layer_.cancel();
|
||||
next_layer_.close();
|
||||
// Don't print out errors, we were expecting a disconnect here
|
||||
SafeDisconnect(get_asio_socket_ptr(&next_layer_));
|
||||
}
|
||||
connected_ = kDisconnected;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue