mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-25 06:34:42 +02:00
Icinga DB Check: fix race-condition with IcingaDB::Start()
IcingaDB::GetConnection() uses IcingaDB::m_Rcon which is only initialized in IcingaDB::Start(), therefore add a nullptr check to the check command. Additionally, as m_Rcon is potentially accessed concurrently, add a copy of the value that is safe for concurrent use.
This commit is contained in:
parent
953e113465
commit
2fafffb85f
@ -32,7 +32,7 @@ REGISTER_TYPE(IcingaDB);
|
|||||||
IcingaDB::IcingaDB()
|
IcingaDB::IcingaDB()
|
||||||
: m_Rcon(nullptr)
|
: m_Rcon(nullptr)
|
||||||
{
|
{
|
||||||
m_Rcon = nullptr;
|
m_RconLocked.store(nullptr);
|
||||||
|
|
||||||
m_WorkQueue.SetName("IcingaDB");
|
m_WorkQueue.SetName("IcingaDB");
|
||||||
|
|
||||||
@ -80,6 +80,7 @@ void IcingaDB::Start(bool runtimeCreated)
|
|||||||
m_Rcon = new RedisConnection(GetHost(), GetPort(), GetPath(), GetPassword(), GetDbIndex(),
|
m_Rcon = new RedisConnection(GetHost(), GetPort(), GetPath(), GetPassword(), GetDbIndex(),
|
||||||
GetEnableTls(), GetInsecureNoverify(), GetCertPath(), GetKeyPath(), GetCaPath(), GetCrlPath(),
|
GetEnableTls(), GetInsecureNoverify(), GetCertPath(), GetKeyPath(), GetCaPath(), GetCrlPath(),
|
||||||
GetTlsProtocolmin(), GetCipherList(), GetConnectTimeout(), GetDebugInfo());
|
GetTlsProtocolmin(), GetCipherList(), GetConnectTimeout(), GetDebugInfo());
|
||||||
|
m_RconLocked.store(m_Rcon);
|
||||||
|
|
||||||
for (const Type::Ptr& type : GetTypes()) {
|
for (const Type::Ptr& type : GetTypes()) {
|
||||||
auto ctype (dynamic_cast<ConfigType*>(type.get()));
|
auto ctype (dynamic_cast<ConfigType*>(type.get()));
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "icingadb/icingadb-ti.hpp"
|
#include "icingadb/icingadb-ti.hpp"
|
||||||
#include "icingadb/redisconnection.hpp"
|
#include "icingadb/redisconnection.hpp"
|
||||||
|
#include "base/atomic.hpp"
|
||||||
#include "base/bulker.hpp"
|
#include "base/bulker.hpp"
|
||||||
#include "base/timer.hpp"
|
#include "base/timer.hpp"
|
||||||
#include "base/workqueue.hpp"
|
#include "base/workqueue.hpp"
|
||||||
@ -46,7 +47,7 @@ public:
|
|||||||
|
|
||||||
inline RedisConnection::Ptr GetConnection()
|
inline RedisConnection::Ptr GetConnection()
|
||||||
{
|
{
|
||||||
return m_Rcon;
|
return m_RconLocked.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -215,6 +216,10 @@ private:
|
|||||||
bool m_ConfigDumpDone;
|
bool m_ConfigDumpDone;
|
||||||
|
|
||||||
RedisConnection::Ptr m_Rcon;
|
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<RedisConnection::Ptr> m_RconLocked;
|
||||||
std::unordered_map<ConfigType*, RedisConnection::Ptr> m_Rcons;
|
std::unordered_map<ConfigType*, RedisConnection::Ptr> m_Rcons;
|
||||||
std::atomic_size_t m_PendingRcons;
|
std::atomic_size_t m_PendingRcons;
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ void IcingadbCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckR
|
|||||||
|
|
||||||
auto redis (conn->GetConnection());
|
auto redis (conn->GetConnection());
|
||||||
|
|
||||||
if (!redis->GetConnected()) {
|
if (!redis || !redis->GetConnected()) {
|
||||||
ReportIcingadbCheck(checkable, commandObj, cr, "Icinga DB CRITICAL: Could not connect to Redis.", ServiceCritical);
|
ReportIcingadbCheck(checkable, commandObj, cr, "Icinga DB CRITICAL: Could not connect to Redis.", ServiceCritical);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user