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

View File

@@ -129,10 +129,11 @@ void CEpgScan::Next()
t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); 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 : /* 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); CFEManager::getInstance()->lockFrontend(live_fe);
#ifdef ENABLE_PIP #ifdef ENABLE_PIP
CFrontend *pip_fe = CZapit::getInstance()->GetPipFrontend(); CFrontend *pip_fe = CZapit::getInstance()->GetPipFrontend();
@@ -158,6 +159,7 @@ void CEpgScan::Next()
if (pip_fe && pip_fe != live_fe) if (pip_fe && pip_fe != live_fe)
CFEManager::getInstance()->unlockFrontend(pip_fe); CFEManager::getInstance()->unlockFrontend(pip_fe);
#endif #endif
CFEManager::getInstance()->Unlock();
if (next_chid) if (next_chid)
g_Zapit->zapTo_epg(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()); INFO("[zapit] zap to %s (%" PRIx64 " tp %" PRIx64 ")", newchannel->getName().c_str(), newchannel->getChannelID(), newchannel->getTransponderId());
#ifdef ENABLE_PIP #ifdef ENABLE_PIP
/* executed async if zap NOWAIT, race possible with record lock/allocate */
CFEManager::getInstance()->Lock();
if (pip_fe) if (pip_fe)
CFEManager::getInstance()->lockFrontend(pip_fe); CFEManager::getInstance()->lockFrontend(pip_fe);
CFrontend * fe = CFEManager::getInstance()->allocateFE(newchannel); CFrontend * fe = CFEManager::getInstance()->allocateFE(newchannel);
@@ -492,6 +494,7 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay
StopPip(); StopPip();
fe = CFEManager::getInstance()->allocateFE(newchannel); fe = CFEManager::getInstance()->allocateFE(newchannel);
} }
CFEManager::getInstance()->Unlock();
#else #else
CFrontend * fe = CFEManager::getInstance()->allocateFE(newchannel); CFrontend * fe = CFEManager::getInstance()->allocateFE(newchannel);
#endif #endif
@@ -681,7 +684,6 @@ bool CZapit::ZapForEpg(const t_channel_id channel_id)
{ {
CZapitChannel* newchannel; CZapitChannel* newchannel;
bool transponder_change; bool transponder_change;
bool ret = false;
if((newchannel = CServiceManager::getInstance()->FindChannel(channel_id)) == NULL) { if((newchannel = CServiceManager::getInstance()->FindChannel(channel_id)) == NULL) {
INFO("channel_id " PRINTF_CHANNEL_ID_TYPE " not found", channel_id); 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); 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); CFEManager::getInstance()->lockFrontend(live_fe);
#ifdef ENABLE_PIP #ifdef ENABLE_PIP
if (pip_fe && pip_fe != live_fe) if (pip_fe && pip_fe != live_fe)
CFEManager::getInstance()->lockFrontend(pip_fe); CFEManager::getInstance()->lockFrontend(pip_fe);
#endif #endif
CFrontend * frontend = CFEManager::getInstance()->allocateFE(newchannel); 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); CFEManager::getInstance()->unlockFrontend(live_fe);
#ifdef ENABLE_PIP #ifdef ENABLE_PIP
if (pip_fe && pip_fe != live_fe) if (pip_fe && pip_fe != live_fe)
CFEManager::getInstance()->unlockFrontend(pip_fe); CFEManager::getInstance()->unlockFrontend(pip_fe);
#endif #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 */ /* set channel/pid volume percent, using current channel_id and pid, if those params is 0 */