From a0b499b05aa453ba4bd5274831db5a9869a26299 Mon Sep 17 00:00:00 2001 From: Yunze Xu Date: Wed, 14 Jun 2023 12:43:15 +0800 Subject: [PATCH 1/2] Close the socket gracefully on Windows Fixes https://github.com/apache/pulsar-client-cpp/issues/261 ### Motivation When closing the socket on Windows, the `ERROR_CONNECTION_ABORTED` error might be returned in the callback of `async_receive`. It's caused by the `socket::close` method is not portable enough, see https://www.boost.org/doc/libs/1_81_0/doc/html/boost_asio/reference/basic_stream_socket/close/overload2.html > For portable behaviour with respect to graceful closure of a connected socket, call shutdown() before closing the socket. ### Modifications Call `shutdown` in `ClientConnection::closeSocket` before calling `close`. In addition, when no bytes are returned or the `eof` error happened, print the logs with debug level whatever the error code is in the read callback. --- lib/ClientConnection.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/ClientConnection.cc b/lib/ClientConnection.cc index 4af5da05..147cfa24 100644 --- a/lib/ClientConnection.cc +++ b/lib/ClientConnection.cc @@ -609,13 +609,13 @@ void ClientConnection::handleRead(const boost::system::error_code& err, size_t b incomingBuffer_.bytesWritten(bytesTransferred); if (err || bytesTransferred == 0) { - if (err) { - if (err == boost::asio::error::operation_aborted) { - LOG_DEBUG(cnxString_ << "Read operation was canceled: " << err.message()); - } else { - LOG_ERROR(cnxString_ << "Read operation failed: " << err.message()); - } - } // else: bytesTransferred == 0, which means server has closed the connection + if (bytesTransferred == 0 || err == boost::asio::error::eof) { + LOG_DEBUG(cnxString_ << "Server closed the connection: " << err.message()); + } else if (err == boost::asio::error::operation_aborted) { + LOG_DEBUG(cnxString_ << "Read operation was canceled: " << err.message()); + } else { + LOG_ERROR(cnxString_ << "Read operation failed: " << err.message()); + } close(); } else if (bytesTransferred < minReadSize) { // Read the remaining part, use a slice of buffer to write on the next @@ -1355,6 +1355,7 @@ Future ClientConnection::newGetSchema(const std::string& top void ClientConnection::closeSocket() { boost::system::error_code err; if (socket_) { + socket_->shutdown(boost::asio::socket_base::shutdown_both, err); socket_->close(err); if (err) { LOG_WARN(cnxString_ << "Failed to close socket: " << err.message()); From 9d6aecaf4928b6cda6e4fab934fe5a61e8703312 Mon Sep 17 00:00:00 2001 From: Yunze Xu Date: Wed, 14 Jun 2023 13:12:39 +0800 Subject: [PATCH 2/2] Handle operation_failed first --- lib/ClientConnection.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ClientConnection.cc b/lib/ClientConnection.cc index 147cfa24..828cdaf4 100644 --- a/lib/ClientConnection.cc +++ b/lib/ClientConnection.cc @@ -609,10 +609,10 @@ void ClientConnection::handleRead(const boost::system::error_code& err, size_t b incomingBuffer_.bytesWritten(bytesTransferred); if (err || bytesTransferred == 0) { - if (bytesTransferred == 0 || err == boost::asio::error::eof) { - LOG_DEBUG(cnxString_ << "Server closed the connection: " << err.message()); - } else if (err == boost::asio::error::operation_aborted) { + if (err == boost::asio::error::operation_aborted) { LOG_DEBUG(cnxString_ << "Read operation was canceled: " << err.message()); + } else if (bytesTransferred == 0 || err == boost::asio::error::eof) { + LOG_DEBUG(cnxString_ << "Server closed the connection: " << err.message()); } else { LOG_ERROR(cnxString_ << "Read operation failed: " << err.message()); }