diff --git a/lib/icingadb/icingadb.cpp b/lib/icingadb/icingadb.cpp index 0d80d006e..f1e538fb0 100644 --- a/lib/icingadb/icingadb.cpp +++ b/lib/icingadb/icingadb.cpp @@ -32,7 +32,7 @@ REGISTER_TYPE(IcingaDB); IcingaDB::IcingaDB() : m_Rcon(nullptr) { - m_Rcon = nullptr; + m_RconLocked.store(nullptr); m_WorkQueue.SetName("IcingaDB"); @@ -80,6 +80,7 @@ void IcingaDB::Start(bool runtimeCreated) m_Rcon = new RedisConnection(GetHost(), GetPort(), GetPath(), GetPassword(), GetDbIndex(), GetEnableTls(), GetInsecureNoverify(), GetCertPath(), GetKeyPath(), GetCaPath(), GetCrlPath(), GetTlsProtocolmin(), GetCipherList(), GetConnectTimeout(), GetDebugInfo()); + m_RconLocked.store(m_Rcon); for (const Type::Ptr& type : GetTypes()) { auto ctype (dynamic_cast(type.get())); diff --git a/lib/icingadb/icingadb.hpp b/lib/icingadb/icingadb.hpp index 075eb36ac..c08f36465 100644 --- a/lib/icingadb/icingadb.hpp +++ b/lib/icingadb/icingadb.hpp @@ -5,6 +5,7 @@ #include "icingadb/icingadb-ti.hpp" #include "icingadb/redisconnection.hpp" +#include "base/atomic.hpp" #include "base/bulker.hpp" #include "base/timer.hpp" #include "base/workqueue.hpp" @@ -46,7 +47,7 @@ public: inline RedisConnection::Ptr GetConnection() { - return m_Rcon; + return m_RconLocked.load(); } template @@ -215,6 +216,10 @@ private: bool m_ConfigDumpDone; RedisConnection::Ptr m_Rcon; + // m_RconLocked containes a copy of the value in m_Rcon where all accesses are guarded by a mutex to allow safe + // concurrent access like from the icingadb check command. It's a copy to still allow fast access without additional + // syncronization to m_Rcon within the IcingaDB feature itself. + Locked m_RconLocked; std::unordered_map m_Rcons; std::atomic_size_t m_PendingRcons; diff --git a/lib/icingadb/icingadbchecktask.cpp b/lib/icingadb/icingadbchecktask.cpp index 25a2084b9..63f5d9910 100644 --- a/lib/icingadb/icingadbchecktask.cpp +++ b/lib/icingadb/icingadbchecktask.cpp @@ -101,7 +101,7 @@ void IcingadbCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckR auto redis (conn->GetConnection()); - if (!redis->GetConnected()) { + if (!redis || !redis->GetConnected()) { ReportIcingadbCheck(checkable, commandObj, cr, "Icinga DB CRITICAL: Could not connect to Redis.", ServiceCritical); return; }