Commit e874d1cb authored by Pavel Vainerman's avatar Pavel Vainerman

(NotifyController): ввёл mutex-ы на списки заказчиков, исправил потенциальную…

(NotifyController): ввёл mutex-ы на списки заказчиков, исправил потенциальную ошибку приводящую к SEGFAULT при работе с заказом пороговых датчиков.. или к "deadlock" (если mutex не так ставить).
parent e73e8f95
......@@ -183,6 +183,10 @@ class IONotifyController:
UniSetTypes::uniset_rwmutex mut;
};
/*! словарь: датчик -> список потребителей */
typedef std::map<UniSetTypes::KeyType,ConsumerListInfo> AskMap;
/*! Информация о пороговом значении */
struct ThresholdInfoExt:
public IONotifyController_i::ThresholdInfo
......@@ -192,13 +196,13 @@ class IONotifyController:
sid(_sid),
invert(inv)
{
id = tid;
hilimit = hi;
lowlimit = low;
state = IONotifyController_i::NormalThreshold;
id = tid;
hilimit = hi;
lowlimit = low;
state = IONotifyController_i::NormalThreshold;
}
ConsumerListInfo clst;
ConsumerListInfo clst; /*!< список заказчиков данного порога */
/*! идентификатор дискретного датчика связанного с данным порогом */
UniSetTypes::ObjectId sid;
......@@ -231,11 +235,9 @@ class IONotifyController:
}
};
/*! список порогов (информация по каждому порогу) */
typedef std::list<ThresholdInfoExt> ThresholdExtList;
/*! массив пар датчик->список потребителей */
typedef std::map<UniSetTypes::KeyType,ConsumerListInfo> AskMap;
struct ThresholdsListInfo
{
ThresholdsListInfo(){}
......@@ -243,13 +245,14 @@ class IONotifyController:
UniversalIO::IOType t=UniversalIO::AI ):
si(si),type(t),list(list){}
IOController_i::SensorInfo si;
UniSetTypes::uniset_rwmutex mut;
IOController_i::SensorInfo si; /*!< аналоговый датчик */
IOStateList::iterator ait;
UniversalIO::IOType type;
ThresholdExtList list;
ThresholdExtList list; /*!< список порогов по данному аналоговому датчику */
};
/*! массив пар [датчик,список порогов] */
/*! словарь: аналоговый датчик --> список порогов по нему */
typedef std::map<UniSetTypes::KeyType,ThresholdsListInfo> AskThresholdMap;
protected:
......
......@@ -142,7 +142,7 @@ long IOController::localGetValue( IOController::IOStateList::iterator& li,
uniset_rwmutex_rlock lock(li->second.val_lock);
return li->second.value;
}
// -------------
ostringstream err;
err << myname << "(localGetValue): Not found sensor (" << si.id << ":" << si.node << ") "
......@@ -174,7 +174,7 @@ void IOController::localSetUndefinedState( IOStateList::iterator& li,
<< "node: " << conf->oind->getMapName(si.node);
throw IOController_i::NameNotFound(err.str().c_str());
}
bool changed = false;
{ // lock
uniset_rwmutex_wrlock lock(li->second.val_lock);
......@@ -184,7 +184,7 @@ void IOController::localSetUndefinedState( IOStateList::iterator& li,
// сперва локальные события...
try
{
{
if( changed )
{
uniset_rwmutex_wrlock l(li->second.undefMutex);
......@@ -682,10 +682,10 @@ IOController_i::SensorInfoSeq* IOController::getSensorSeq( const IDSeq& lst )
(*res)[i] = it->second;
continue;
}
// элемент не найден...
(*res)[i].si.id = DefaultObjectId;
(*res)[i].si.node = DefaultObjectId;
(*res)[i].si.node = DefaultObjectId;
(*res)[i].undefined = true;
}
......
......@@ -130,7 +130,7 @@ bool IONotifyController::removeConsumer( ConsumerListInfo& lst, const ConsumerIn
uniset_rwmutex_wrlock l(lst.mut);
for( ConsumerList::iterator li=lst.clst.begin();li!=lst.clst.end(); ++li )
{
if( li->id == cons.id && li->node == cons.node )
if( li->id==cons.id && li->node==cons.node )
{
lst.clst.erase(li);
return true;
......@@ -215,7 +215,7 @@ void IONotifyController::ask(AskMap& askLst, const IOController_i::SensorInfo& s
UniSetTypes::KeyType k( key(si.id,si.node) );
AskMap::iterator askIterator = askLst.find(k);
switch (cmd)
switch (cmd)
{
case UniversalIO::UIONotify: // заказ
case UniversalIO::UIONotifyChange:
......@@ -265,12 +265,15 @@ void IONotifyController::ask(AskMap& askLst, const IOController_i::SensorInfo& s
{
if( askIterator!=askLst.end() ) // существует
{
// ConsumerList lst(askIterator->second);
if( removeConsumer(askIterator->second, cons) )
{
uniset_rwmutex_wrlock l(askIterator->second.mut);
if( askIterator->second.clst.empty() )
askLst.erase(askIterator);
{
// не удаляем, т.к. могут поломаться итераторы
// используемые в это время в других потоках..
// askLst.erase(askIterator);
}
else
{
try
......@@ -375,8 +378,6 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
*/
void IONotifyController::send( ConsumerListInfo& lst, UniSetTypes::SensorMessage& sm )
{
return;
TransportMessage tmsg;
uniset_rwmutex_wrlock l(lst.mut);
......@@ -699,9 +700,13 @@ bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoEx
{
if( removeConsumer(it->clst, ci) )
{
uniset_rwmutex_wrlock lock(it->clst.mut);
if( it->clst.clst.empty() )
lst.erase(it);
/* Не удаляем датчик из списка, чтобы не поломать итераторы
которые могут использоваться в этот момент в других потоках*/
// uniset_rwmutex_wrlock lock(it->clst.mut);
// if( it->clst.clst.empty() )
// lst.erase(it);
return true;
}
}
......@@ -711,26 +716,22 @@ bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoEx
}
// --------------------------------------------------------------------------------------------------------------
void IONotifyController::checkThreshold( IOStateList::iterator& li,
const IOController_i::SensorInfo& si,
bool send_msg )
const IOController_i::SensorInfo& si,
bool send_msg )
{
// {
// uniset_rwmutex_rlock lock(trshMutex);
// поиск списка порогов
UniSetTypes::KeyType skey( key(si.id,si.node) );
AskThresholdMap::iterator lst = askTMap.end();
{
uniset_rwmutex_rlock lock(trshMutex);
lst = askTMap.find(skey);
if( lst == askTMap.end() )
return;
if( lst->second.list.empty() )
return;
}
}
if( li == myioEnd() )
li = myiofind(skey);
......@@ -758,6 +759,8 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
tm.tv_sec = 0; tm.tv_usec = 0;
gettimeofday(&tm,&tz);
{
uniset_rwmutex_rlock l(lst->second.mut);
for( ThresholdExtList::iterator it=lst->second.list.begin(); it!=lst->second.list.end(); ++it )
{
// Используем здесь sm.value чтобы не делать ещё раз lock на li->second.value
......@@ -804,7 +807,7 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
{
try
{
localSetValue(it->sit,SensorInfo(it->sid),(sm.threshold ? 1:0),getId());
localSetValue(it->sit,SensorInfo(it->sid),(sm.threshold ? 1:0),getId());
}
catch( UniSetTypes::Exception& ex )
{
......@@ -816,7 +819,7 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
if( send_msg )
send(it->clst, sm);
}
// } // unlock
}
}
// --------------------------------------------------------------------------------------------------------------
IONotifyController::ThresholdExtList::iterator IONotifyController::findThreshold( UniSetTypes::KeyType key, UniSetTypes::ThresholdId tid )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment