Close server connections and shutdown coroutines immediately on disconnect

This commit is contained in:
Alexander A. Klimov 2019-06-05 10:32:20 +02:00
parent 06fc6055d5
commit ad28380884
5 changed files with 34 additions and 13 deletions

View File

@ -31,7 +31,8 @@ using namespace icinga;
auto const l_ServerHeader ("Icinga/" + Application::GetAppVersion()); auto const l_ServerHeader ("Icinga/" + Application::GetAppVersion());
HttpServerConnection::HttpServerConnection(const String& identity, bool authenticated, const std::shared_ptr<AsioTlsStream>& stream) HttpServerConnection::HttpServerConnection(const String& identity, bool authenticated, const std::shared_ptr<AsioTlsStream>& stream)
: m_Stream(stream), m_Seen(Utility::GetTime()), m_IoStrand(stream->get_executor().context()), m_ShuttingDown(false), m_HasStartedStreaming(false) : m_Stream(stream), m_Seen(Utility::GetTime()), m_IoStrand(stream->get_executor().context()), m_ShuttingDown(false), m_HasStartedStreaming(false),
m_CheckLivenessTimer(stream->get_executor().context())
{ {
if (authenticated) { if (authenticated) {
m_ApiUser = ApiUser::GetByClientCN(identity); m_ApiUser = ApiUser::GetByClientCN(identity);
@ -80,6 +81,13 @@ void HttpServerConnection::Disconnect()
} catch (...) { } catch (...) {
} }
try {
m_Stream->lowest_layer().cancel();
} catch (...) {
}
m_CheckLivenessTimer.cancel();
auto listener (ApiListener::GetInstance()); auto listener (ApiListener::GetInstance());
if (listener) { if (listener) {
@ -529,11 +537,11 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
void HttpServerConnection::CheckLiveness(boost::asio::yield_context yc) void HttpServerConnection::CheckLiveness(boost::asio::yield_context yc)
{ {
boost::asio::deadline_timer timer (m_Stream->get_executor().context()); boost::system::error_code ec;
for (;;) { for (;;) {
timer.expires_from_now(boost::posix_time::seconds(5)); m_CheckLivenessTimer.expires_from_now(boost::posix_time::seconds(5));
timer.async_wait(yc); m_CheckLivenessTimer.async_wait(yc[ec]);
if (m_ShuttingDown) { if (m_ShuttingDown) {
break; break;

View File

@ -7,6 +7,7 @@
#include "base/string.hpp" #include "base/string.hpp"
#include "base/tlsstream.hpp" #include "base/tlsstream.hpp"
#include <memory> #include <memory>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service_strand.hpp> #include <boost/asio/io_service_strand.hpp>
#include <boost/asio/spawn.hpp> #include <boost/asio/spawn.hpp>
@ -39,6 +40,7 @@ private:
boost::asio::io_service::strand m_IoStrand; boost::asio::io_service::strand m_IoStrand;
bool m_ShuttingDown; bool m_ShuttingDown;
bool m_HasStartedStreaming; bool m_HasStartedStreaming;
boost::asio::deadline_timer m_CheckLivenessTimer;
void ProcessMessages(boost::asio::yield_context yc); void ProcessMessages(boost::asio::yield_context yc);
void CheckLiveness(boost::asio::yield_context yc); void CheckLiveness(boost::asio::yield_context yc);

View File

@ -7,9 +7,9 @@
#include "base/configtype.hpp" #include "base/configtype.hpp"
#include "base/logger.hpp" #include "base/logger.hpp"
#include "base/utility.hpp" #include "base/utility.hpp"
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/spawn.hpp> #include <boost/asio/spawn.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp> #include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <boost/system/system_error.hpp>
using namespace icinga; using namespace icinga;
@ -17,11 +17,11 @@ REGISTER_APIFUNCTION(Heartbeat, event, &JsonRpcConnection::HeartbeatAPIHandler);
void JsonRpcConnection::HandleAndWriteHeartbeats(boost::asio::yield_context yc) void JsonRpcConnection::HandleAndWriteHeartbeats(boost::asio::yield_context yc)
{ {
boost::asio::deadline_timer timer (m_Stream->get_executor().context()); boost::system::error_code ec;
for (;;) { for (;;) {
timer.expires_from_now(boost::posix_time::seconds(10)); m_HeartbeatTimer.expires_from_now(boost::posix_time::seconds(10));
timer.async_wait(yc); m_HeartbeatTimer.async_wait(yc[ec]);
if (m_ShuttingDown) { if (m_ShuttingDown) {
break; break;

View File

@ -16,9 +16,9 @@
#include "base/tlsstream.hpp" #include "base/tlsstream.hpp"
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/spawn.hpp> #include <boost/asio/spawn.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp> #include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <boost/system/system_error.hpp>
#include <boost/thread/once.hpp> #include <boost/thread/once.hpp>
using namespace icinga; using namespace icinga;
@ -32,7 +32,8 @@ JsonRpcConnection::JsonRpcConnection(const String& identity, bool authenticated,
const std::shared_ptr<AsioTlsStream>& stream, ConnectionRole role) const std::shared_ptr<AsioTlsStream>& stream, ConnectionRole role)
: m_Identity(identity), m_Authenticated(authenticated), m_Stream(stream), : m_Identity(identity), m_Authenticated(authenticated), m_Stream(stream),
m_Role(role), m_Timestamp(Utility::GetTime()), m_Seen(Utility::GetTime()), m_NextHeartbeat(0), m_IoStrand(stream->get_executor().context()), m_Role(role), m_Timestamp(Utility::GetTime()), m_Seen(Utility::GetTime()), m_NextHeartbeat(0), m_IoStrand(stream->get_executor().context()),
m_OutgoingMessagesQueued(stream->get_executor().context()), m_WriterDone(stream->get_executor().context()), m_ShuttingDown(false) m_OutgoingMessagesQueued(stream->get_executor().context()), m_WriterDone(stream->get_executor().context()), m_ShuttingDown(false),
m_CheckLivenessTimer(stream->get_executor().context()), m_HeartbeatTimer(stream->get_executor().context())
{ {
if (authenticated) if (authenticated)
m_Endpoint = Endpoint::GetByName(identity); m_Endpoint = Endpoint::GetByName(identity);
@ -206,6 +207,14 @@ void JsonRpcConnection::Disconnect()
} catch (...) { } catch (...) {
} }
try {
m_Stream->lowest_layer().cancel();
} catch (...) {
}
m_CheckLivenessTimer.cancel();
m_HeartbeatTimer.cancel();
CpuBoundWork removeClient (yc); CpuBoundWork removeClient (yc);
if (m_Endpoint) { if (m_Endpoint) {
@ -310,11 +319,11 @@ Value SetLogPositionHandler(const MessageOrigin::Ptr& origin, const Dictionary::
void JsonRpcConnection::CheckLiveness(boost::asio::yield_context yc) void JsonRpcConnection::CheckLiveness(boost::asio::yield_context yc)
{ {
boost::asio::deadline_timer timer (m_Stream->get_executor().context()); boost::system::error_code ec;
for (;;) { for (;;) {
timer.expires_from_now(boost::posix_time::seconds(30)); m_CheckLivenessTimer.expires_from_now(boost::posix_time::seconds(30));
timer.async_wait(yc); m_CheckLivenessTimer.async_wait(yc[ec]);
if (m_ShuttingDown) { if (m_ShuttingDown) {
break; break;

View File

@ -11,6 +11,7 @@
#include "base/workqueue.hpp" #include "base/workqueue.hpp"
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service_strand.hpp> #include <boost/asio/io_service_strand.hpp>
#include <boost/asio/spawn.hpp> #include <boost/asio/spawn.hpp>
@ -77,6 +78,7 @@ private:
AsioConditionVariable m_OutgoingMessagesQueued; AsioConditionVariable m_OutgoingMessagesQueued;
AsioConditionVariable m_WriterDone; AsioConditionVariable m_WriterDone;
bool m_ShuttingDown; bool m_ShuttingDown;
boost::asio::deadline_timer m_CheckLivenessTimer, m_HeartbeatTimer;
void HandleIncomingMessages(boost::asio::yield_context yc); void HandleIncomingMessages(boost::asio::yield_context yc);
void WriteOutgoingMessages(boost::asio::yield_context yc); void WriteOutgoingMessages(boost::asio::yield_context yc);