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: ...@@ -183,6 +183,10 @@ class IONotifyController:
UniSetTypes::uniset_rwmutex mut; UniSetTypes::uniset_rwmutex mut;
}; };
/*! словарь: датчик -> список потребителей */
typedef std::map<UniSetTypes::KeyType,ConsumerListInfo> AskMap;
/*! Информация о пороговом значении */ /*! Информация о пороговом значении */
struct ThresholdInfoExt: struct ThresholdInfoExt:
public IONotifyController_i::ThresholdInfo public IONotifyController_i::ThresholdInfo
...@@ -198,7 +202,7 @@ class IONotifyController: ...@@ -198,7 +202,7 @@ class IONotifyController:
state = IONotifyController_i::NormalThreshold; state = IONotifyController_i::NormalThreshold;
} }
ConsumerListInfo clst; ConsumerListInfo clst; /*!< список заказчиков данного порога */
/*! идентификатор дискретного датчика связанного с данным порогом */ /*! идентификатор дискретного датчика связанного с данным порогом */
UniSetTypes::ObjectId sid; UniSetTypes::ObjectId sid;
...@@ -231,11 +235,9 @@ class IONotifyController: ...@@ -231,11 +235,9 @@ class IONotifyController:
} }
}; };
/*! список порогов (информация по каждому порогу) */
typedef std::list<ThresholdInfoExt> ThresholdExtList; typedef std::list<ThresholdInfoExt> ThresholdExtList;
/*! массив пар датчик->список потребителей */
typedef std::map<UniSetTypes::KeyType,ConsumerListInfo> AskMap;
struct ThresholdsListInfo struct ThresholdsListInfo
{ {
ThresholdsListInfo(){} ThresholdsListInfo(){}
...@@ -243,13 +245,14 @@ class IONotifyController: ...@@ -243,13 +245,14 @@ class IONotifyController:
UniversalIO::IOType t=UniversalIO::AI ): UniversalIO::IOType t=UniversalIO::AI ):
si(si),type(t),list(list){} si(si),type(t),list(list){}
IOController_i::SensorInfo si; UniSetTypes::uniset_rwmutex mut;
IOController_i::SensorInfo si; /*!< аналоговый датчик */
IOStateList::iterator ait; IOStateList::iterator ait;
UniversalIO::IOType type; UniversalIO::IOType type;
ThresholdExtList list; ThresholdExtList list; /*!< список порогов по данному аналоговому датчику */
}; };
/*! массив пар [датчик,список порогов] */ /*! словарь: аналоговый датчик --> список порогов по нему */
typedef std::map<UniSetTypes::KeyType,ThresholdsListInfo> AskThresholdMap; typedef std::map<UniSetTypes::KeyType,ThresholdsListInfo> AskThresholdMap;
protected: protected:
......
...@@ -130,7 +130,7 @@ bool IONotifyController::removeConsumer( ConsumerListInfo& lst, const ConsumerIn ...@@ -130,7 +130,7 @@ bool IONotifyController::removeConsumer( ConsumerListInfo& lst, const ConsumerIn
uniset_rwmutex_wrlock l(lst.mut); uniset_rwmutex_wrlock l(lst.mut);
for( ConsumerList::iterator li=lst.clst.begin();li!=lst.clst.end(); ++li ) 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); lst.clst.erase(li);
return true; return true;
...@@ -265,12 +265,15 @@ void IONotifyController::ask(AskMap& askLst, const IOController_i::SensorInfo& s ...@@ -265,12 +265,15 @@ void IONotifyController::ask(AskMap& askLst, const IOController_i::SensorInfo& s
{ {
if( askIterator!=askLst.end() ) // существует if( askIterator!=askLst.end() ) // существует
{ {
// ConsumerList lst(askIterator->second);
if( removeConsumer(askIterator->second, cons) ) if( removeConsumer(askIterator->second, cons) )
{ {
uniset_rwmutex_wrlock l(askIterator->second.mut); uniset_rwmutex_wrlock l(askIterator->second.mut);
if( askIterator->second.clst.empty() ) if( askIterator->second.clst.empty() )
askLst.erase(askIterator); {
// не удаляем, т.к. могут поломаться итераторы
// используемые в это время в других потоках..
// askLst.erase(askIterator);
}
else else
{ {
try try
...@@ -375,8 +378,6 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li, ...@@ -375,8 +378,6 @@ void IONotifyController::localSetValue( IOController::IOStateList::iterator& li,
*/ */
void IONotifyController::send( ConsumerListInfo& lst, UniSetTypes::SensorMessage& sm ) void IONotifyController::send( ConsumerListInfo& lst, UniSetTypes::SensorMessage& sm )
{ {
return;
TransportMessage tmsg; TransportMessage tmsg;
uniset_rwmutex_wrlock l(lst.mut); uniset_rwmutex_wrlock l(lst.mut);
...@@ -699,9 +700,13 @@ bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoEx ...@@ -699,9 +700,13 @@ bool IONotifyController::removeThreshold( ThresholdExtList& lst, ThresholdInfoEx
{ {
if( removeConsumer(it->clst, ci) ) 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; return true;
} }
} }
...@@ -714,16 +719,12 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li, ...@@ -714,16 +719,12 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
const IOController_i::SensorInfo& si, const IOController_i::SensorInfo& si,
bool send_msg ) bool send_msg )
{ {
// {
// uniset_rwmutex_rlock lock(trshMutex);
// поиск списка порогов // поиск списка порогов
UniSetTypes::KeyType skey( key(si.id,si.node) ); UniSetTypes::KeyType skey( key(si.id,si.node) );
AskThresholdMap::iterator lst = askTMap.end(); AskThresholdMap::iterator lst = askTMap.end();
{ {
uniset_rwmutex_rlock lock(trshMutex); uniset_rwmutex_rlock lock(trshMutex);
lst = askTMap.find(skey); lst = askTMap.find(skey);
if( lst == askTMap.end() ) if( lst == askTMap.end() )
return; return;
...@@ -758,6 +759,8 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li, ...@@ -758,6 +759,8 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
tm.tv_sec = 0; tm.tv_usec = 0; tm.tv_sec = 0; tm.tv_usec = 0;
gettimeofday(&tm,&tz); gettimeofday(&tm,&tz);
{
uniset_rwmutex_rlock l(lst->second.mut);
for( ThresholdExtList::iterator it=lst->second.list.begin(); it!=lst->second.list.end(); ++it ) for( ThresholdExtList::iterator it=lst->second.list.begin(); it!=lst->second.list.end(); ++it )
{ {
// Используем здесь sm.value чтобы не делать ещё раз lock на li->second.value // Используем здесь sm.value чтобы не делать ещё раз lock на li->second.value
...@@ -816,7 +819,7 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li, ...@@ -816,7 +819,7 @@ void IONotifyController::checkThreshold( IOStateList::iterator& li,
if( send_msg ) if( send_msg )
send(it->clst, sm); send(it->clst, sm);
} }
// } // unlock }
} }
// -------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------
IONotifyController::ThresholdExtList::iterator IONotifyController::findThreshold( UniSetTypes::KeyType key, UniSetTypes::ThresholdId tid ) 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