nhttpd: try to fix threaded nhttp crashes (again)

Origin commit data
------------------
Commit: 14a73c3b80
Author: [CST] Focus <focus.cst@gmail.com>
Date: 2016-03-08 (Tue, 08 Mar 2016)
This commit is contained in:
[CST] Focus
2016-03-08 18:05:34 +03:00
parent 029ead9bcb
commit 86c6632755
4 changed files with 80 additions and 64 deletions

View File

@@ -807,7 +807,8 @@ int CControlAPI::rc_send(int ev, unsigned int code, unsigned int value)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// The code here is based on rcsim. Thx Carjay! // The code here is based on rcsim. Thx Carjay!
void CControlAPI::RCEmCGI(CyhookHandler *hh) { void CControlAPI::RCEmCGI(CyhookHandler *hh)
{
if (hh->ParamList.empty()) { if (hh->ParamList.empty()) {
hh->SendError(); hh->SendError();
return; return;
@@ -1038,39 +1039,38 @@ void CControlAPI::LogolistCGI(CyhookHandler *hh)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// get actual and next event data for given channel // get actual and next event data for given channel
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
std::string CControlAPI::_GetBouquetActualEPGItem(CyhookHandler *hh, CZapitChannel * channel) { std::string CControlAPI::_GetBouquetActualEPGItem(CyhookHandler *hh, CZapitChannel * channel)
{
std::string result, firstEPG, secondEPG = ""; std::string result, firstEPG, secondEPG = "";
t_channel_id current_channel = CZapit::getInstance()->GetCurrentChannelID(); t_channel_id current_channel = CZapit::getInstance()->GetCurrentChannelID();
std::string timestr; std::string timestr;
CShortEPGData epg; CShortEPGData epg;
CSectionsdClient::responseGetCurrentNextInfoChannelID currentNextInfo; CSectionsdClient::responseGetCurrentNextInfoChannelID currentNextInfo;
CChannelEvent *event; CChannelEvent event;
NeutrinoAPI->Lock(); NeutrinoAPI->GetChannelEvent(channel->getChannelID(), event);
event = NeutrinoAPI->ChannelListEvents[channel->getChannelID()];
NeutrinoAPI->Unlock();
bool return_epginfo = (hh->ParamList["epginfo"] != "false"); bool return_epginfo = (hh->ParamList["epginfo"] != "false");
result += hh->outPair("isActiveChannel", (channel->getChannelID() == current_channel) ? "true" : "false", false); result += hh->outPair("isActiveChannel", (channel->getChannelID() == current_channel) ? "true" : "false", false);
if (event) { if (event.eventID) {
int percentage = 100; int percentage = 100;
if (event->duration > 0) if (event.duration > 0)
percentage = 100 * (time(NULL) - event->startTime) / event->duration; percentage = 100 * (time(NULL) - event.startTime) / event.duration;
CEitManager::getInstance()->getCurrentNextServiceKey(channel->getChannelID(), currentNextInfo); CEitManager::getInstance()->getCurrentNextServiceKey(channel->getChannelID(), currentNextInfo);
timestr = timeString(event->startTime); timestr = timeString(event.startTime);
firstEPG += hh->outPair("eventid", string_printf("%llu", currentNextInfo.current_uniqueKey), true); firstEPG += hh->outPair("eventid", string_printf("%llu", currentNextInfo.current_uniqueKey), true);
firstEPG += hh->outPair("description", hh->outValue(event->description), true); firstEPG += hh->outPair("description", hh->outValue(event.description), true);
if (return_epginfo && CEitManager::getInstance()->getEPGidShort(currentNextInfo.current_uniqueKey, &epg)) if (return_epginfo && CEitManager::getInstance()->getEPGidShort(currentNextInfo.current_uniqueKey, &epg))
{ {
firstEPG += hh->outPair("info1", hh->outValue(epg.info1), true); firstEPG += hh->outPair("info1", hh->outValue(epg.info1), true);
firstEPG += hh->outPair("info2", hh->outValue(epg.info2), true); firstEPG += hh->outPair("info2", hh->outValue(epg.info2), true);
} }
firstEPG += hh->outPair("startTime", timestr, true); firstEPG += hh->outPair("startTime", timestr, true);
firstEPG += hh->outPair("timeTotal", string_printf("%d", event->duration / 60), true); firstEPG += hh->outPair("timeTotal", string_printf("%d", event.duration / 60), true);
firstEPG += hh->outPair("timeElapsed", string_printf("%d", (time(NULL) - event->startTime) / 60), true); firstEPG += hh->outPair("timeElapsed", string_printf("%d", (time(NULL) - event.startTime) / 60), true);
firstEPG += hh->outPair("percentage", string_printf("%d", percentage), false); firstEPG += hh->outPair("percentage", string_printf("%d", percentage), false);
if (currentNextInfo.flags & CSectionsdClient::epgflags::has_next) { if (currentNextInfo.flags & CSectionsdClient::epgflags::has_next) {
@@ -1100,7 +1100,8 @@ std::string CControlAPI::_GetBouquetActualEPGItem(CyhookHandler *hh, CZapitChann
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// produce data (collection) for given channel // produce data (collection) for given channel
std::string CControlAPI::_GetBouquetWriteItem(CyhookHandler *hh, CZapitChannel * channel, int bouquetNr, int channelNr) { std::string CControlAPI::_GetBouquetWriteItem(CyhookHandler *hh, CZapitChannel * channel, int bouquetNr, int channelNr)
{
std::string result = ""; std::string result = "";
bool isEPGdetails = !(hh->ParamList["epg"].empty()); bool isEPGdetails = !(hh->ParamList["epg"].empty());
if (hh->outType == json || hh->outType == xml) { if (hh->outType == json || hh->outType == xml) {
@@ -1123,18 +1124,16 @@ std::string CControlAPI::_GetBouquetWriteItem(CyhookHandler *hh, CZapitChannel *
result = hh->outArrayItem("channel", result, false); result = hh->outArrayItem("channel", result, false);
} }
else { else {
CChannelEvent *event; CChannelEvent event;
NeutrinoAPI->Lock(); NeutrinoAPI->GetChannelEvent(channel->getChannelID(), event);
event = NeutrinoAPI->ChannelListEvents[channel->getChannelID()];
NeutrinoAPI->Unlock();
if (event && isEPGdetails) { if (event.eventID && isEPGdetails) {
result += string_printf("%u " result += string_printf("%u "
PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS
" %s (%s)\n", " %s (%s)\n",
channelNr, channelNr,
channel->getChannelID(), channel->getChannelID(),
channel->getName().c_str(), event->description.c_str()); channel->getName().c_str(), event.description.c_str());
} else { } else {
result += string_printf("%u " result += string_printf("%u "
PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS
@@ -1212,7 +1211,8 @@ std::string CControlAPI::_GetBouquetWriteItem(CyhookHandler *hh, CZapitChannel *
* @endcode * @endcode
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void CControlAPI::GetBouquetCGI(CyhookHandler *hh) { void CControlAPI::GetBouquetCGI(CyhookHandler *hh)
{
TOutType outType = hh->outStart(true /*old mode*/); TOutType outType = hh->outStart(true /*old mode*/);
std::string result = ""; std::string result = "";
@@ -1412,7 +1412,8 @@ void CControlAPI::GetChannelCGI(CyhookHandler *hh)
* @endcode * @endcode
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void CControlAPI::GetBouquetsCGI(CyhookHandler *hh) { void CControlAPI::GetBouquetsCGI(CyhookHandler *hh)
{
bool show_hidden = true; bool show_hidden = true;
bool encode = false; bool encode = false;
std::string result = ""; std::string result = "";
@@ -1472,10 +1473,12 @@ void CControlAPI::GetBouquetsCGI(CyhookHandler *hh) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// details EPG Information for channelid // details EPG Information for channelid
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
std::string CControlAPI::channelEPGformated(CyhookHandler *hh, int bouquetnr, t_channel_id channel_id, int max, long stoptime) { std::string CControlAPI::channelEPGformated(CyhookHandler *hh, int bouquetnr, t_channel_id channel_id, int max, long stoptime)
{
std::string result = ""; std::string result = "";
std::string channelData = ""; std::string channelData = "";
CEitManager::getInstance()->getEventsServiceKey(channel_id, NeutrinoAPI->eList); CChannelEventList eList;
CEitManager::getInstance()->getEventsServiceKey(channel_id, eList);
channelData += hh->outPair("channel_name", hh->outValue(NeutrinoAPI->GetServiceName(channel_id)), true); channelData += hh->outPair("channel_name", hh->outValue(NeutrinoAPI->GetServiceName(channel_id)), true);
channelData += hh->outPair("channel_id", string_printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS, channel_id), true); channelData += hh->outPair("channel_id", string_printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS, channel_id), true);
channelData += hh->outPair("channel_short_id", string_printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS, channel_id & 0xFFFFFFFFFFFFULL), (bouquetnr > -1)); channelData += hh->outPair("channel_short_id", string_printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS, channel_id & 0xFFFFFFFFFFFFULL), (bouquetnr > -1));
@@ -1486,7 +1489,7 @@ std::string CControlAPI::channelEPGformated(CyhookHandler *hh, int bouquetnr, t_
int i = 0; int i = 0;
CChannelEventList::iterator eventIterator; CChannelEventList::iterator eventIterator;
bool isFirstLine = true; bool isFirstLine = true;
for (eventIterator = NeutrinoAPI->eList.begin(); eventIterator != NeutrinoAPI->eList.end(); ++eventIterator, i++) { for (eventIterator = eList.begin(); eventIterator != eList.end(); ++eventIterator, i++) {
if ((max != -1 && i >= max) || (stoptime != -1 && eventIterator->startTime >= stoptime)) if ((max != -1 && i >= max) || (stoptime != -1 && eventIterator->startTime >= stoptime))
break; break;
std::string prog = ""; std::string prog = "";
@@ -1536,7 +1539,8 @@ std::string CControlAPI::channelEPGformated(CyhookHandler *hh, int bouquetnr, t_
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Detailed EPG list in XML or JSON // Detailed EPG list in XML or JSON
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CControlAPI::epgDetailList(CyhookHandler *hh) { void CControlAPI::epgDetailList(CyhookHandler *hh)
{
// ------ get parameters ------- // ------ get parameters -------
// max = maximal output items // max = maximal output items
int max = -1; int max = -1;
@@ -1579,7 +1583,6 @@ void CControlAPI::epgDetailList(CyhookHandler *hh) {
hh->outStart(true /*old mode*/); hh->outStart(true /*old mode*/);
std::string result = ""; std::string result = "";
NeutrinoAPI->eList.clear();
if (bouquetnr >= 0 || all_bouquets) { if (bouquetnr >= 0 || all_bouquets) {
int bouquet_size = (int) g_bouquetManager->Bouquets.size(); int bouquet_size = (int) g_bouquetManager->Bouquets.size();
int start_bouquet = 0; int start_bouquet = 0;
@@ -1829,8 +1832,8 @@ void CControlAPI::SendFoundEvents(CyhookHandler *hh, bool xml_format)
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void CControlAPI::EpgCGI(CyhookHandler *hh) { void CControlAPI::EpgCGI(CyhookHandler *hh)
NeutrinoAPI->eList.clear(); {
bool param_empty = hh->ParamList.empty(); bool param_empty = hh->ParamList.empty();
hh->SetHeader(HTTP_OK, "text/plain; charset=UTF-8"); // default hh->SetHeader(HTTP_OK, "text/plain; charset=UTF-8"); // default
// Detailed EPG list in XML or JSON // Detailed EPG list in XML or JSON
@@ -1841,24 +1844,22 @@ void CControlAPI::EpgCGI(CyhookHandler *hh) {
else if (param_empty || hh->ParamList["1"] == "ext") { else if (param_empty || hh->ParamList["1"] == "ext") {
hh->SetHeader(HTTP_OK, "text/plain; charset=UTF-8"); hh->SetHeader(HTTP_OK, "text/plain; charset=UTF-8");
bool isExt = (hh->ParamList["1"] == "ext"); bool isExt = (hh->ParamList["1"] == "ext");
CChannelEvent *event = NULL; CChannelEvent event;
NeutrinoAPI->GetChannelEvents(); NeutrinoAPI->GetChannelEvents();
int mode = NeutrinoAPI->Zapit->getMode(); int mode = NeutrinoAPI->Zapit->getMode();
CBouquetManager::ChannelIterator cit = mode == CZapitClient::MODE_RADIO ? g_bouquetManager->radioChannelsBegin() : g_bouquetManager->tvChannelsBegin(); CBouquetManager::ChannelIterator cit = mode == CZapitClient::MODE_RADIO ? g_bouquetManager->radioChannelsBegin() : g_bouquetManager->tvChannelsBegin();
for (; !(cit.EndOfChannels()); cit++) { for (; !(cit.EndOfChannels()); cit++) {
CZapitChannel * channel = *cit; CZapitChannel * channel = *cit;
NeutrinoAPI->Lock(); NeutrinoAPI->GetChannelEvent(channel->getChannelID(), event);
event = NeutrinoAPI->ChannelListEvents[channel->getChannelID()]; if (event.eventID) {
NeutrinoAPI->Unlock();
if (event) {
if (!isExt) { if (!isExt) {
hh->printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS hh->printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS
" %llu %s\n", channel->getChannelID(), event->eventID, event->description.c_str()); " %llu %s\n", channel->getChannelID(), event.eventID, event.description.c_str());
} }
else { // ext output else { // ext output
hh->printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS hh->printf(PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS
" %ld %u %llu %s\n", channel->getChannelID(), event->startTime, event->duration, event->eventID, event->description.c_str()); " %ld %u %llu %s\n", channel->getChannelID(), event.startTime, event.duration, event.eventID, event.description.c_str());
} }
} }
} }
@@ -1897,9 +1898,10 @@ void CControlAPI::EpgCGI(CyhookHandler *hh) {
else if (!(hh->ParamList["id"].empty())) { else if (!(hh->ParamList["id"].empty())) {
t_channel_id channel_id = 0; t_channel_id channel_id = 0;
sscanf(hh->ParamList["id"].c_str(), SCANF_CHANNEL_ID_TYPE, &channel_id); sscanf(hh->ParamList["id"].c_str(), SCANF_CHANNEL_ID_TYPE, &channel_id);
CEitManager::getInstance()->getEventsServiceKey(channel_id, NeutrinoAPI->eList); CChannelEventList eList;
CEitManager::getInstance()->getEventsServiceKey(channel_id, eList);
CChannelEventList::iterator eventIterator; CChannelEventList::iterator eventIterator;
for (eventIterator = NeutrinoAPI->eList.begin(); eventIterator != NeutrinoAPI->eList.end(); ++eventIterator) { for (eventIterator = eList.begin(); eventIterator != eList.end(); ++eventIterator) {
CShortEPGData epg; CShortEPGData epg;
if (CEitManager::getInstance()->getEPGidShort(eventIterator->eventID, &epg)) { if (CEitManager::getInstance()->getEPGidShort(eventIterator->eventID, &epg)) {
hh->printf("%llu %ld %d\n", eventIterator->eventID, eventIterator->startTime, eventIterator->duration); hh->printf("%llu %ld %d\n", eventIterator->eventID, eventIterator->startTime, eventIterator->duration);
@@ -2113,10 +2115,11 @@ void CControlAPI::LCDAction(CyhookHandler *hh)
void CControlAPI::SendEventList(CyhookHandler *hh, t_channel_id channel_id) void CControlAPI::SendEventList(CyhookHandler *hh, t_channel_id channel_id)
{ {
int pos = 0; int pos = 0;
CEitManager::getInstance()->getEventsServiceKey(channel_id, NeutrinoAPI->eList); CChannelEventList eList;
CEitManager::getInstance()->getEventsServiceKey(channel_id, eList);
CChannelEventList::iterator eventIterator; CChannelEventList::iterator eventIterator;
for (eventIterator = NeutrinoAPI->eList.begin(); eventIterator != NeutrinoAPI->eList.end(); ++eventIterator, pos++) for (eventIterator = eList.begin(); eventIterator != eList.end(); ++eventIterator, pos++)
hh->printf("%llu %ld %d %s\n", eventIterator->eventID, eventIterator->startTime, eventIterator->duration, eventIterator->description.c_str()); hh->printf("%llu %ld %d %s\n", eventIterator->eventID, eventIterator->startTime, eventIterator->duration, eventIterator->description.c_str());
} }
@@ -3141,7 +3144,8 @@ void CControlAPI::logoCGI(CyhookHandler *hh)
* @endcode * @endcode
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
void CControlAPI::ConfigCGI(CyhookHandler *hh) { void CControlAPI::ConfigCGI(CyhookHandler *hh)
{
bool load = true; bool load = true;
CConfigFile *Config = new CConfigFile(','); CConfigFile *Config = new CConfigFile(',');
ConfigDataMap conf; ConfigDataMap conf;
@@ -3264,7 +3268,8 @@ void CControlAPI::ConfigCGI(CyhookHandler *hh) {
* action =new_folder|delete|read_file|write_file|set_properties * action =new_folder|delete|read_file|write_file|set_properties
*/ */
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CControlAPI::FileCGI(CyhookHandler *hh) { void CControlAPI::FileCGI(CyhookHandler *hh)
{
std::string result = ""; std::string result = "";
if (hh->ParamList["action"] == "list") { // directory list: action=list&path=<path> if (hh->ParamList["action"] == "list") { // directory list: action=list&path=<path>
@@ -3400,7 +3405,8 @@ void CControlAPI::FileCGI(CyhookHandler *hh) {
* @endcode * @endcode
*/ */
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CControlAPI::StatfsCGI(CyhookHandler *hh) { void CControlAPI::StatfsCGI(CyhookHandler *hh)
{
std::string result = ""; std::string result = "";
if (hh->ParamList["path"].empty()) if (hh->ParamList["path"].empty())
@@ -3459,7 +3465,8 @@ void CControlAPI::StatfsCGI(CyhookHandler *hh) {
* *
*/ */
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CControlAPI::getDirCGI(CyhookHandler *hh) { void CControlAPI::getDirCGI(CyhookHandler *hh)
{
std::string result = ""; std::string result = "";
std::string item = ""; std::string item = "";
bool isFirstLine = true; bool isFirstLine = true;
@@ -3519,7 +3526,8 @@ void CControlAPI::getDirCGI(CyhookHandler *hh) {
} }
//Helpfunction to get subdirs of a dir //Helpfunction to get subdirs of a dir
std::string CControlAPI::getSubdirectories(CyhookHandler *hh, std::string path, std::string result) { std::string CControlAPI::getSubdirectories(CyhookHandler *hh, std::string path, std::string result)
{
std::string item = ""; std::string item = "";
std::string dirname; std::string dirname;
DIR *dirp; DIR *dirp;

View File

@@ -291,6 +291,15 @@ bool CNeutrinoAPI::GetChannelEvents(void)
return true; return true;
} }
void CNeutrinoAPI::GetChannelEvent(t_channel_id channel_id, CChannelEvent &event)
{
OpenThreads::ScopedPointerLock<OpenThreads::Mutex> lock(pmutex);
event.eventID = 0;
CChannelEvent * evt = ChannelListEvents[channel_id];
if (evt)
event = *evt;
}
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
std::string CNeutrinoAPI::GetServiceName(t_channel_id channel_id) std::string CNeutrinoAPI::GetServiceName(t_channel_id channel_id)

View File

@@ -25,23 +25,27 @@ bool _initialize_iso639_map(void);
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
class CNeutrinoAPI class CNeutrinoAPI
{ {
private:
CChannelEventList eList;
OpenThreads::Mutex *pmutex; OpenThreads::Mutex *pmutex;
std::map<unsigned, CChannelEvent *> ChannelListEvents;
// complete channellists
//CZapitClient::BouquetChannelList RadioChannelList,TVChannelList;
// events of actual channel
// List of available tv bouquets
//std::map<int, CZapitClient::BouquetChannelList> TVBouquetsList;
// List of available radio bouquets
//std::map<int, CZapitClient::BouquetChannelList> RadioBouquetsList;
// List of bouquets
CZapitClient::BouquetList BouquetList;
public:
// Clientlibs // Clientlibs
CSectionsdClient *Sectionsd; CSectionsdClient *Sectionsd;
CZapitClient *Zapit; CZapitClient *Zapit;
CTimerdClient *Timerd; CTimerdClient *Timerd;
CEventServer *EventServer; CEventServer *EventServer;
// complete channellists
CZapitClient::BouquetChannelList RadioChannelList,TVChannelList;
// events of actual channel
std::map<unsigned, CChannelEvent *> ChannelListEvents;
// List of available tv bouquets
std::map<int, CZapitClient::BouquetChannelList> TVBouquetsList;
// List of available radio bouquets
std::map<int, CZapitClient::BouquetChannelList> RadioBouquetsList;
// List of bouquets
CZapitClient::BouquetList BouquetList;
//bool standby_mode; //bool standby_mode;
@@ -85,14 +89,14 @@ public:
CNeutrinoAPI(); CNeutrinoAPI();
~CNeutrinoAPI(void); ~CNeutrinoAPI(void);
CChannelEventList eList;
CNeutrinoYParser *NeutrinoYParser; CNeutrinoYParser *NeutrinoYParser;
CControlAPI *ControlAPI; CControlAPI *ControlAPI;
void Lock() { pmutex->lock(); } void Lock() { pmutex->lock(); }
void Unlock() { pmutex->unlock(); } void Unlock() { pmutex->unlock(); }
void GetChannelEvent(t_channel_id channel_id, CChannelEvent &event);
friend class CNeutrinoYParser; // Backreference //friend class CNeutrinoYParser; // Backreference
friend class CControlAPI; //friend class CControlAPI;
}; };
#endif /*__nhttpd_neutrinoapi_h__*/ #endif /*__nhttpd_neutrinoapi_h__*/

View File

@@ -359,12 +359,7 @@ std::string CNeutrinoYParser::func_get_bouquets_with_epg(CyhookHandler *hh, std:
{ {
CZapitChannel * channel = channels[j]; CZapitChannel * channel = channels[j];
CChannelEvent event; CChannelEvent event;
event.eventID = 0; NeutrinoAPI->GetChannelEvent(channel->getChannelID(), event);
NeutrinoAPI->Lock();
CChannelEvent * evt = NeutrinoAPI->ChannelListEvents[channel->getChannelID()];
if (evt)
event = *evt;
NeutrinoAPI->Unlock();
classname = (i++ & 1) ? 'a' : 'b'; classname = (i++ & 1) ? 'a' : 'b';
if (channel->getChannelID() == current_channel) if (channel->getChannelID() == current_channel)