From: Gunnar Beutner Date: Sat, 14 Dec 2013 22:10:37 +0000 (+0100) Subject: Fix race conditions in the config compiler. X-Git-Tag: v0.0.6~32 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0af81f2da245c848a653cdf17599be5a945ba06a;p=icinga2 Fix race conditions in the config compiler. Fixes #5335 --- diff --git a/lib/config/configitem.cpp b/lib/config/configitem.cpp index 0b1f242b4..f2b2c72e4 100644 --- a/lib/config/configitem.cpp +++ b/lib/config/configitem.cpp @@ -103,12 +103,12 @@ ExpressionList::Ptr ConfigItem::GetExpressionList(void) const return m_ExpressionList; } -void ConfigItem::Link(void) +ExpressionList::Ptr ConfigItem::GetLinkedExpressionList(void) { ASSERT(OwnsLock()); if (m_LinkedExpressionList) - return; + return m_LinkedExpressionList; m_LinkedExpressionList = make_shared(); @@ -121,31 +121,25 @@ void ConfigItem::Link(void) " exist (" << m_DebugInfo << ")"; ConfigCompilerContext::GetInstance()->AddMessage(true, message.str()); } else { - parent->Link(); + ExpressionList::Ptr pexprl; + + { + ObjectLock olock(parent); + pexprl = parent->GetLinkedExpressionList(); + } - ExpressionList::Ptr pexprl = parent->m_LinkedExpressionList; m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, pexprl, m_DebugInfo)); } } m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, m_ExpressionList, m_DebugInfo)); -} - -ExpressionList::Ptr ConfigItem::GetLinkedExpressionList(void) -{ - ASSERT(OwnsLock()); - - if (!m_LinkedExpressionList) - Link(); return m_LinkedExpressionList; } Dictionary::Ptr ConfigItem::GetProperties(void) { - ASSERT(!OwnsLock()); - - ObjectLock olock(this); + ASSERT(OwnsLock()); if (!m_Properties) { m_Properties = make_shared(); @@ -181,7 +175,13 @@ DynamicObject::Ptr ConfigItem::Commit(void) if (IsAbstract()) return DynamicObject::Ptr(); - Dictionary::Ptr properties = GetProperties(); + Dictionary::Ptr properties; + + { + ObjectLock olock(this); + + properties = GetProperties(); + } DynamicObject::Ptr dobj = dtype->CreateObject(properties); dobj->Register(); diff --git a/lib/config/configitem.h b/lib/config/configitem.h index bd69daff4..69b66a392 100644 --- a/lib/config/configitem.h +++ b/lib/config/configitem.h @@ -65,7 +65,6 @@ public: static void DiscardItems(void); private: - void Link(void); ExpressionList::Ptr GetExpressionList(void) const; String m_Type; /**< The object type. */ diff --git a/lib/config/configtype.cpp b/lib/config/configtype.cpp index 5c18ddcfa..30a2a766f 100644 --- a/lib/config/configtype.cpp +++ b/lib/config/configtype.cpp @@ -79,11 +79,21 @@ void ConfigType::ValidateItem(const ConfigItem::Ptr& item) if (item->IsAbstract()) return; - Dictionary::Ptr attrs = item->GetProperties(); + Dictionary::Ptr attrs; + DebugInfo debugInfo; + String type, name; + + { + ObjectLock olock(item); + + attrs = item->GetProperties(); + debugInfo = item->GetDebugInfo(); + type = item->GetType(); + name = item->GetName(); + } std::vector locations; - DebugInfo debugInfo = item->GetDebugInfo(); - locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "') at " + debugInfo.Path + ":" + Convert::ToString(debugInfo.FirstLine)); + locations.push_back("Object '" + name + "' (Type: '" + type + "') at " + debugInfo.Path + ":" + Convert::ToString(debugInfo.FirstLine)); std::vector ruleLists; AddParentRules(ruleLists, GetSelf()); diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index adf476771..74e3a9c53 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -155,8 +155,16 @@ void Host::UpdateSlaveServices(void) path.push_back("services"); path.push_back(kv.first); + ExpressionList::Ptr exprl; + + { + ObjectLock ilock(item); + + exprl = item->GetLinkedExpressionList(); + } + DebugInfo di; - item->GetLinkedExpressionList()->FindDebugInfoPath(path, di); + exprl->FindDebugInfoPath(path, di); if (di.Path.IsEmpty()) di = item->GetDebugInfo(); @@ -185,7 +193,7 @@ void Host::UpdateSlaveServices(void) /* Clone attributes from the service expression list. */ ExpressionList::Ptr svc_exprl = make_shared(); - item->GetLinkedExpressionList()->ExtractPath(path, svc_exprl); + exprl->ExtractPath(path, svc_exprl); builder->AddExpressionList(svc_exprl); diff --git a/lib/icinga/service-downtime.cpp b/lib/icinga/service-downtime.cpp index 793452799..f014ab262 100644 --- a/lib/icinga/service-downtime.cpp +++ b/lib/icinga/service-downtime.cpp @@ -335,8 +335,16 @@ void Service::UpdateSlaveScheduledDowntimes(void) path.push_back("scheduled_downtimes"); path.push_back(kv.first); + ExpressionList::Ptr exprl; + + { + ObjectLock ilock(item); + + exprl = item->GetLinkedExpressionList(); + } + DebugInfo di; - item->GetLinkedExpressionList()->FindDebugInfoPath(path, di); + exprl->FindDebugInfoPath(path, di); if (di.Path.IsEmpty()) di = item->GetDebugInfo(); @@ -361,7 +369,7 @@ void Service::UpdateSlaveScheduledDowntimes(void) /* Clone attributes from the scheduled downtime expression list. */ ExpressionList::Ptr sd_exprl = make_shared(); - item->GetLinkedExpressionList()->ExtractPath(path, sd_exprl); + exprl->ExtractPath(path, sd_exprl); builder->AddExpressionList(sd_exprl); diff --git a/lib/icinga/service-notification.cpp b/lib/icinga/service-notification.cpp index b4808659c..083b1d52e 100644 --- a/lib/icinga/service-notification.cpp +++ b/lib/icinga/service-notification.cpp @@ -114,8 +114,16 @@ void Service::UpdateSlaveNotifications(void) path.push_back("notifications"); path.push_back(kv.first); + ExpressionList::Ptr exprl; + + { + ObjectLock ilock(exprl); + + exprl = item->GetLinkedExpressionList(); + } + DebugInfo di; - item->GetLinkedExpressionList()->FindDebugInfoPath(path, di); + exprl->FindDebugInfoPath(path, di); if (di.Path.IsEmpty()) di = item->GetDebugInfo(); @@ -140,7 +148,7 @@ void Service::UpdateSlaveNotifications(void) /* Clone attributes from the notification expression list. */ ExpressionList::Ptr nfc_exprl = make_shared(); - item->GetLinkedExpressionList()->ExtractPath(path, nfc_exprl); + exprl->ExtractPath(path, nfc_exprl); builder->AddExpressionList(nfc_exprl);