From cdb0e0ef215dbdfb1843045ab68f1523b8ac139f Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Mon, 12 Aug 2013 16:05:20 +0400 Subject: [PATCH] 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 --- src/driver/record.cpp | 4 ++++ src/driver/scanepg.cpp | 6 ++++-- src/zapit/src/zapit.cpp | 31 +++++++++++++++++++------------ 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/driver/record.cpp b/src/driver/record.cpp index 123d6d012..d6bfd4398 100644 --- a/src/driver/record.cpp +++ b/src/driver/record.cpp @@ -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; diff --git a/src/driver/scanepg.cpp b/src/driver/scanepg.cpp index 5bbf95ef7..b0e2075d5 100644 --- a/src/driver/scanepg.cpp +++ b/src/driver/scanepg.cpp @@ -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); } diff --git a/src/zapit/src/zapit.cpp b/src/zapit/src/zapit.cpp index 01447934f..373a371c8 100644 --- a/src/zapit/src/zapit.cpp +++ b/src/zapit/src/zapit.cpp @@ -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 */