@@ -411,7 +411,18 @@ typedef ASIO::detail::socket_option::integer<IPPROTO_TCP, TCP_KEEPIDLE> tcp_keep
411411 * at this point the connection is deemed valid to be used by clients of this class
412412 */
413413void ClientConnection::handleTcpConnected (const ASIO_ERROR & err, const tcp::endpoint& endpoint) {
414+ if (connectTimeoutTask_) {
415+ connectTimeoutTask_->stop ();
416+ }
417+ Lock lock (mutex_);
414418 if (!err) {
419+ if (isClosed ()) {
420+ ASIO_ERROR err;
421+ socket_->close (err);
422+ connectPromise_.setFailed (ResultAlreadyClosed);
423+ LOG_INFO (cnxString_ << " Connection already closed" );
424+ return ;
425+ }
415426 std::stringstream cnxStringStream;
416427 try {
417428 cnxStringStream << " [" << socket_->local_endpoint () << " -> " << socket_->remote_endpoint ()
@@ -430,11 +441,6 @@ void ClientConnection::handleTcpConnected(const ASIO_ERROR& err, const tcp::endp
430441 << " , physical address:" << physicalAddress_);
431442 }
432443
433- Lock lock (mutex_);
434- if (isClosed ()) {
435- LOG_INFO (cnxString_ << " Connection already closed" );
436- return ;
437- }
438444 state_ = TcpConnected;
439445 lock.unlock ();
440446
@@ -484,10 +490,12 @@ void ClientConnection::handleTcpConnected(const ASIO_ERROR& err, const tcp::endp
484490 auto tlsSocket = tlsSocket_;
485491 // socket and ssl::stream objects must exist until async_handshake is done, otherwise segmentation
486492 // fault might happen
487- auto callback = [weakSelf, socket, tlsSocket](const ASIO_ERROR & err) {
493+ pendingOperations_++;
494+ auto callback = [this , weakSelf, socket, tlsSocket](const ASIO_ERROR & err) {
488495 auto self = weakSelf.lock ();
489496 if (self) {
490- self->handleHandshake (err);
497+ handleHandshake (err);
498+ pendingOperations_--;
491499 }
492500 };
493501 tlsSocket_->async_handshake (ASIO ::ssl::stream<tcp::socket>::client,
@@ -496,6 +504,7 @@ void ClientConnection::handleTcpConnected(const ASIO_ERROR& err, const tcp::endp
496504 handleHandshake (ASIO_SUCCESS );
497505 }
498506 } else {
507+ lock.unlock ();
499508 LOG_ERROR (cnxString_ << " Failed to establish connection to " << endpoint << " : " << err.message ());
500509 if (err == ASIO ::error::operation_aborted) {
501510 close ();
@@ -596,11 +605,13 @@ void ClientConnection::tcpConnectAsync() {
596605 LOG_DEBUG (cnxString_ << " Resolving " << service_url.host () << " :" << service_url.port ());
597606
598607 auto weakSelf = weak_from_this ();
608+ pendingOperations_++;
599609 resolver_->async_resolve (service_url.host (), std::to_string (service_url.port ()),
600- [weakSelf](auto err, const auto & results) {
610+ [this , weakSelf](auto err, const auto & results) {
601611 auto self = weakSelf.lock ();
602612 if (self) {
603- self->handleResolve (err, results);
613+ handleResolve (err, results);
614+ pendingOperations_--;
604615 }
605616 });
606617}
@@ -642,12 +653,15 @@ void ClientConnection::handleResolve(ASIO_ERROR err, const tcp::resolver::result
642653 ptr->connectTimeoutTask_ ->stop ();
643654 });
644655 connectTimeoutTask_->start ();
645- ASIO::async_connect (*socket_, results, [weakSelf](const ASIO_ERROR & err, const tcp::endpoint& endpoint) {
646- auto self = weakSelf.lock ();
647- if (self) {
648- self->handleTcpConnected (err, endpoint);
649- }
650- });
656+ pendingOperations_++;
657+ ASIO::async_connect (*socket_, results,
658+ [this , weakSelf](const ASIO_ERROR & err, const tcp::endpoint& endpoint) {
659+ auto self = weakSelf.lock ();
660+ if (self) {
661+ handleTcpConnected (err, endpoint);
662+ pendingOperations_--;
663+ }
664+ });
651665}
652666
653667void ClientConnection::readNextCommand () {
@@ -1079,6 +1093,7 @@ void ClientConnection::sendCommand(const SharedBuffer& cmd) {
10791093
10801094 if (pendingWriteOperations_++ == 0 ) {
10811095 // Write immediately to socket
1096+ lock.unlock ();
10821097 if (tlsSocket_) {
10831098 auto weakSelf = weak_from_this ();
10841099 auto callback = [weakSelf, cmd]() {
@@ -1162,6 +1177,7 @@ void ClientConnection::sendPendingCommands() {
11621177 pendingWriteBuffers_.pop_front ();
11631178
11641179 auto self = shared_from_this ();
1180+ lock.unlock ();
11651181 if (any.type () == typeid (SharedBuffer)) {
11661182 SharedBuffer buffer = std::any_cast<SharedBuffer>(any);
11671183 asyncWrite (buffer.const_asio_buffer (),
@@ -1297,16 +1313,19 @@ void ClientConnection::close(Result result, bool detach) {
12971313 if (isClosed ()) {
12981314 return ;
12991315 }
1300- state_ = Disconnected;
13011316
13021317 if (socket_) {
13031318 ASIO_ERROR err;
1304- socket_->shutdown (ASIO ::socket_base::shutdown_both, err);
1305- socket_->close (err);
1306- if (err) {
1307- LOG_WARN (cnxString_ << " Failed to close socket: " << err.message ());
1308- }
1319+ if (state_ != Pending) {
1320+ socket_->shutdown (ASIO ::socket_base::shutdown_both, err);
1321+ socket_->close (err);
1322+ if (err) {
1323+ LOG_WARN (cnxString_ << " Failed to close socket: " << err.message ());
1324+ }
1325+ } // else: there is an ongoing connect operation, the socket will be closed after the operation
1326+ // succeeds in `handleTcpConnected`
13091327 }
1328+ state_ = Disconnected;
13101329 if (tlsSocket_) {
13111330 ASIO_ERROR err;
13121331 tlsSocket_->lowest_layer ().close (err);
0 commit comments