diff --git a/lib/remote/jsonrpcconnection.cpp b/lib/remote/jsonrpcconnection.cpp index d49c0b359..b8ae22aaa 100644 --- a/lib/remote/jsonrpcconnection.cpp +++ b/lib/remote/jsonrpcconnection.cpp @@ -250,28 +250,42 @@ void JsonRpcConnection::Disconnect() if (!m_ShuttingDown.exchange(true)) { JsonRpcConnection::Ptr keepAlive (this); - IoEngine::SpawnCoroutine(m_IoStrand, [this, keepAlive](asio::yield_context yc) { - Log(LogWarning, "JsonRpcConnection") - << "API client disconnected for identity '" << m_Identity << "'"; + Log(LogNotice, "JsonRpcConnection") + << "Disconnecting API client for identity '" << m_Identity << "'"; + + IoEngine::SpawnCoroutine(m_IoStrand, [this, keepAlive](asio::yield_context yc) { + m_OutgoingMessagesQueued.Set(); + + { + Timeout writerTimeout( + m_IoStrand, + boost::posix_time::seconds(5), + [this]() { + // The writer coroutine could not finish soon enough to unblock the waiter down blow, + // so we have to do this on our own, and the coroutine will be terminated forcibly when + // the ops on the underlying socket are cancelled. + boost::system::error_code ec; + m_Stream->lowest_layer().cancel(ec); + } + ); + + m_WriterDone.Wait(yc); + // We don't need to explicitly cancel the timer here; its destructor will handle it for us. + } + + m_CheckLivenessTimer.cancel(); + m_HeartbeatTimer.cancel(); + + m_Stream->GracefulDisconnect(m_IoStrand, yc); - // We need to unregister the endpoint client as soon as possible not to confuse Icinga 2, - // given that Endpoint::GetConnected() is just performing a check that the endpoint's client - // cache is not empty, which could result in an already disconnected endpoint never trying to - // reconnect again. See #7444. if (m_Endpoint) { m_Endpoint->RemoveClient(this); } else { ApiListener::GetInstance()->RemoveAnonymousClient(this); } - m_OutgoingMessagesQueued.Set(); - - m_WriterDone.Wait(yc); - - m_CheckLivenessTimer.cancel(); - m_HeartbeatTimer.cancel(); - - m_Stream->GracefulDisconnect(m_IoStrand, yc); + Log(LogWarning, "JsonRpcConnection") + << "API client disconnected for identity '" << m_Identity << "'"; }); } }