driver/record.cpp, driver/scanepg.cpp, zapit/src/zapit.cpp: try to prevent race

while lock/allocate frontend in case of possible concurrent usage in neutrino and zapit threads
This commit is contained in:
[CST] Focus
2013-08-12 16:05:20 +04:00
parent 79845b8fe2
commit cdb0e0ef21
3 changed files with 27 additions and 14 deletions

View File

@@ -1621,6 +1621,8 @@ bool CRecordManager::CutBackNeutrino(const t_channel_id channel_id, CFrontend *
if(live_channel_id != channel_id) {
/* first try to get frontend for record with locked live */
bool unlock = true;
/* executed in neutrino thread - possible race with zap NOWAIT and epg scan zap */
CFEManager::getInstance()->Lock();
CFEManager::getInstance()->lockFrontend(live_fe);
frontend = CFEManager::getInstance()->allocateFE(channel, true);
if (frontend == NULL) {
@@ -1629,6 +1631,8 @@ bool CRecordManager::CutBackNeutrino(const t_channel_id channel_id, CFrontend *
CFEManager::getInstance()->unlockFrontend(live_fe);
frontend = CFEManager::getInstance()->allocateFE(channel, true);
}
CFEManager::getInstance()->Unlock();
if (frontend == NULL)
return false;

View File

@@ -129,10 +129,11 @@ void CEpgScan::Next()
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID();
CFrontend *live_fe = CZapit::getInstance()->GetLiveFrontend();
/* executed in neutrino thread - possible race with locks in zapit zap NOWAIT :
send zaTo_NOWAIT -> EIT_COMPLETE from sectionsd -> zap and this at the same time
send zapTo_NOWAIT -> EIT_COMPLETE from sectionsd -> zap and this at the same time
*/
CFEManager::getInstance()->Lock();
CFrontend *live_fe = CZapit::getInstance()->GetLiveFrontend();
CFEManager::getInstance()->lockFrontend(live_fe);
#ifdef ENABLE_PIP
CFrontend *pip_fe = CZapit::getInstance()->GetPipFrontend();
@@ -158,6 +159,7 @@ void CEpgScan::Next()
if (pip_fe && pip_fe != live_fe)
CFEManager::getInstance()->unlockFrontend(pip_fe);
#endif
CFEManager::getInstance()->Unlock();
if (next_chid)
g_Zapit->zapTo_epg(next_chid);
}

View File

@@ -483,6 +483,8 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay
INFO("[zapit] zap to %s (%" PRIx64 " tp %" PRIx64 ")", newchannel->getName().c_str(), newchannel->getChannelID(), newchannel->getTransponderId());
#ifdef ENABLE_PIP
/* executed async if zap NOWAIT, race possible with record lock/allocate */
CFEManager::getInstance()->Lock();
if (pip_fe)
CFEManager::getInstance()->lockFrontend(pip_fe);
CFrontend * fe = CFEManager::getInstance()->allocateFE(newchannel);
@@ -492,6 +494,7 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay
StopPip();
fe = CFEManager::getInstance()->allocateFE(newchannel);
}
CFEManager::getInstance()->Unlock();
#else
CFrontend * fe = CFEManager::getInstance()->allocateFE(newchannel);
#endif
@@ -681,7 +684,6 @@ bool CZapit::ZapForEpg(const t_channel_id channel_id)
{
CZapitChannel* newchannel;
bool transponder_change;
bool ret = false;
if((newchannel = CServiceManager::getInstance()->FindChannel(channel_id)) == NULL) {
INFO("channel_id " PRINTF_CHANNEL_ID_TYPE " not found", channel_id);
@@ -689,29 +691,34 @@ bool CZapit::ZapForEpg(const t_channel_id channel_id)
}
INFO("%s: %s (%" PRIx64 ")", __FUNCTION__, newchannel->getName().c_str(), channel_id);
/* executed async in zapit thread, race possible with record lock/allocate */
CFEManager::getInstance()->Lock();
CFEManager::getInstance()->lockFrontend(live_fe);
#ifdef ENABLE_PIP
if (pip_fe && pip_fe != live_fe)
CFEManager::getInstance()->lockFrontend(pip_fe);
#endif
CFrontend * frontend = CFEManager::getInstance()->allocateFE(newchannel);
if(frontend == NULL) {
ERROR("Cannot get frontend\n");
goto __error;
}
if(!TuneChannel(frontend, newchannel, transponder_change))
goto __error;
if(ParsePatPmt(newchannel))
ret = true;
__error:
CFEManager::getInstance()->unlockFrontend(live_fe);
#ifdef ENABLE_PIP
if (pip_fe && pip_fe != live_fe)
CFEManager::getInstance()->unlockFrontend(pip_fe);
#endif
return ret;
CFEManager::getInstance()->Unlock();
if(frontend == NULL) {
ERROR("Cannot get frontend\n");
return false;
}
if(!TuneChannel(frontend, newchannel, transponder_change))
return false;
if(!ParsePatPmt(newchannel))
return false;
return true;
}
/* set channel/pid volume percent, using current channel_id and pid, if those params is 0 */