From 7ed5c6a2c76a8917d994e4e76d86c966784a2dc8 Mon Sep 17 00:00:00 2001 From: Yonas Habteab Date: Thu, 31 Oct 2024 10:19:40 +0100 Subject: [PATCH] JsonRpcConnection: Don't drop client from cache prematurely PR #7445 incorrectly assumed that a peer that had already disconnected and never reconnected was due to the endpoint client being dropped after a successful socket shutdown. However, the issue at that time was that there was not a single timeout guards that could cancel the `async_shutdown` call, petentially blocking indefinetely. Although removing the client from cache early might have allowed the endpoint to reconnect, it did not resolve the underlying problem. Now that we have a proper cancellation timeout, we can wait until the currently used socket is fully closed before dropping the client from our cache. When our socket termination works reliably, the `ApiListener` reconnect timer should attempt to reconnect this endpoint after the next tick. Additionally, we now have logs both for before and after socket termination, which may help identify if it is hanging somewhere in between. --- lib/remote/jsonrpcconnection.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/remote/jsonrpcconnection.cpp b/lib/remote/jsonrpcconnection.cpp index 35aa22fff..54378a0d3 100644 --- a/lib/remote/jsonrpcconnection.cpp +++ b/lib/remote/jsonrpcconnection.cpp @@ -211,16 +211,6 @@ void JsonRpcConnection::Disconnect() Log(LogWarning, "JsonRpcConnection") << "API client disconnected for identity '" << m_Identity << "'"; - // 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); @@ -229,6 +219,12 @@ void JsonRpcConnection::Disconnect() m_HeartbeatTimer.cancel(); m_Stream->GracefulDisconnect(m_IoStrand, yc); + + if (m_Endpoint) { + m_Endpoint->RemoveClient(this); + } else { + ApiListener::GetInstance()->RemoveAnonymousClient(this); + } }); } }