Fix race conditions in the config compiler.

Fixes #5335
This commit is contained in:
Gunnar Beutner 2013-12-14 23:10:37 +01:00
parent 4563bb355f
commit 0af81f2da2
6 changed files with 59 additions and 26 deletions

View File

@ -103,12 +103,12 @@ ExpressionList::Ptr ConfigItem::GetExpressionList(void) const
return m_ExpressionList; return m_ExpressionList;
} }
void ConfigItem::Link(void) ExpressionList::Ptr ConfigItem::GetLinkedExpressionList(void)
{ {
ASSERT(OwnsLock()); ASSERT(OwnsLock());
if (m_LinkedExpressionList) if (m_LinkedExpressionList)
return; return m_LinkedExpressionList;
m_LinkedExpressionList = make_shared<ExpressionList>(); m_LinkedExpressionList = make_shared<ExpressionList>();
@ -121,31 +121,25 @@ void ConfigItem::Link(void)
" exist (" << m_DebugInfo << ")"; " exist (" << m_DebugInfo << ")";
ConfigCompilerContext::GetInstance()->AddMessage(true, message.str()); ConfigCompilerContext::GetInstance()->AddMessage(true, message.str());
} else { } 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, pexprl, m_DebugInfo));
} }
} }
m_LinkedExpressionList->AddExpression(Expression("", OperatorExecute, m_ExpressionList, 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; return m_LinkedExpressionList;
} }
Dictionary::Ptr ConfigItem::GetProperties(void) Dictionary::Ptr ConfigItem::GetProperties(void)
{ {
ASSERT(!OwnsLock()); ASSERT(OwnsLock());
ObjectLock olock(this);
if (!m_Properties) { if (!m_Properties) {
m_Properties = make_shared<Dictionary>(); m_Properties = make_shared<Dictionary>();
@ -181,7 +175,13 @@ DynamicObject::Ptr ConfigItem::Commit(void)
if (IsAbstract()) if (IsAbstract())
return DynamicObject::Ptr(); return DynamicObject::Ptr();
Dictionary::Ptr properties = GetProperties(); Dictionary::Ptr properties;
{
ObjectLock olock(this);
properties = GetProperties();
}
DynamicObject::Ptr dobj = dtype->CreateObject(properties); DynamicObject::Ptr dobj = dtype->CreateObject(properties);
dobj->Register(); dobj->Register();

View File

@ -65,7 +65,6 @@ public:
static void DiscardItems(void); static void DiscardItems(void);
private: private:
void Link(void);
ExpressionList::Ptr GetExpressionList(void) const; ExpressionList::Ptr GetExpressionList(void) const;
String m_Type; /**< The object type. */ String m_Type; /**< The object type. */

View File

@ -79,11 +79,21 @@ void ConfigType::ValidateItem(const ConfigItem::Ptr& item)
if (item->IsAbstract()) if (item->IsAbstract())
return; 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<String> locations; std::vector<String> locations;
DebugInfo debugInfo = item->GetDebugInfo(); locations.push_back("Object '" + name + "' (Type: '" + type + "') at " + debugInfo.Path + ":" + Convert::ToString(debugInfo.FirstLine));
locations.push_back("Object '" + item->GetName() + "' (Type: '" + item->GetType() + "') at " + debugInfo.Path + ":" + Convert::ToString(debugInfo.FirstLine));
std::vector<TypeRuleList::Ptr> ruleLists; std::vector<TypeRuleList::Ptr> ruleLists;
AddParentRules(ruleLists, GetSelf()); AddParentRules(ruleLists, GetSelf());

View File

@ -155,8 +155,16 @@ void Host::UpdateSlaveServices(void)
path.push_back("services"); path.push_back("services");
path.push_back(kv.first); path.push_back(kv.first);
ExpressionList::Ptr exprl;
{
ObjectLock ilock(item);
exprl = item->GetLinkedExpressionList();
}
DebugInfo di; DebugInfo di;
item->GetLinkedExpressionList()->FindDebugInfoPath(path, di); exprl->FindDebugInfoPath(path, di);
if (di.Path.IsEmpty()) if (di.Path.IsEmpty())
di = item->GetDebugInfo(); di = item->GetDebugInfo();
@ -185,7 +193,7 @@ void Host::UpdateSlaveServices(void)
/* Clone attributes from the service expression list. */ /* Clone attributes from the service expression list. */
ExpressionList::Ptr svc_exprl = make_shared<ExpressionList>(); ExpressionList::Ptr svc_exprl = make_shared<ExpressionList>();
item->GetLinkedExpressionList()->ExtractPath(path, svc_exprl); exprl->ExtractPath(path, svc_exprl);
builder->AddExpressionList(svc_exprl); builder->AddExpressionList(svc_exprl);

View File

@ -335,8 +335,16 @@ void Service::UpdateSlaveScheduledDowntimes(void)
path.push_back("scheduled_downtimes"); path.push_back("scheduled_downtimes");
path.push_back(kv.first); path.push_back(kv.first);
ExpressionList::Ptr exprl;
{
ObjectLock ilock(item);
exprl = item->GetLinkedExpressionList();
}
DebugInfo di; DebugInfo di;
item->GetLinkedExpressionList()->FindDebugInfoPath(path, di); exprl->FindDebugInfoPath(path, di);
if (di.Path.IsEmpty()) if (di.Path.IsEmpty())
di = item->GetDebugInfo(); di = item->GetDebugInfo();
@ -361,7 +369,7 @@ void Service::UpdateSlaveScheduledDowntimes(void)
/* Clone attributes from the scheduled downtime expression list. */ /* Clone attributes from the scheduled downtime expression list. */
ExpressionList::Ptr sd_exprl = make_shared<ExpressionList>(); ExpressionList::Ptr sd_exprl = make_shared<ExpressionList>();
item->GetLinkedExpressionList()->ExtractPath(path, sd_exprl); exprl->ExtractPath(path, sd_exprl);
builder->AddExpressionList(sd_exprl); builder->AddExpressionList(sd_exprl);

View File

@ -114,8 +114,16 @@ void Service::UpdateSlaveNotifications(void)
path.push_back("notifications"); path.push_back("notifications");
path.push_back(kv.first); path.push_back(kv.first);
ExpressionList::Ptr exprl;
{
ObjectLock ilock(exprl);
exprl = item->GetLinkedExpressionList();
}
DebugInfo di; DebugInfo di;
item->GetLinkedExpressionList()->FindDebugInfoPath(path, di); exprl->FindDebugInfoPath(path, di);
if (di.Path.IsEmpty()) if (di.Path.IsEmpty())
di = item->GetDebugInfo(); di = item->GetDebugInfo();
@ -140,7 +148,7 @@ void Service::UpdateSlaveNotifications(void)
/* Clone attributes from the notification expression list. */ /* Clone attributes from the notification expression list. */
ExpressionList::Ptr nfc_exprl = make_shared<ExpressionList>(); ExpressionList::Ptr nfc_exprl = make_shared<ExpressionList>();
item->GetLinkedExpressionList()->ExtractPath(path, nfc_exprl); exprl->ExtractPath(path, nfc_exprl);
builder->AddExpressionList(nfc_exprl); builder->AddExpressionList(nfc_exprl);