diff --git a/src/gui/luainstance.cpp b/src/gui/luainstance.cpp index 315e2cbff..3877bedd0 100644 --- a/src/gui/luainstance.cpp +++ b/src/gui/luainstance.cpp @@ -34,9 +34,6 @@ #include #include #include -#include -#include -#include #include "luainstance.h" #include @@ -2476,170 +2473,3 @@ int CLuaInstance::LuaConfigFileDelete(lua_State *L) } // -------------------------------------------------------------------------------- - -#if 0 -For testing try: - -cat < /lib/tuxbox/luaplugins/test.lua -for i,v in ipairs(arg) do - print(tostring(i) .. "\t" .. tostring(v)) -end -return "ok" -EOT - -followed by luaclient test a b c d -#endif -class luaserver_data -{ - public: - int fd; - std::vector argv; - std::string script; - - luaserver_data(int _fd, std::string &_script) { - fd = dup(_fd); - fcntl(fd, F_SETFD, FD_CLOEXEC); - script = _script; - } - ~luaserver_data(void) { - close(fd); - } - -}; - -static int luaserver_count = 0; -static pthread_mutex_t luaserver_mutex; - -static void luaserver_lock(void) -{ - pthread_mutex_lock(&luaserver_mutex); -} - -static void luaserver_unlock(void) -{ - pthread_mutex_unlock(&luaserver_mutex); -} - -static void *luaserver_thread(void *arg) { - set_threadname(__func__); - luaserver_lock(); - luaserver_count++; - luaserver_unlock(); - sem_post(&CNeutrinoApp::getInstance()->lua_did_run); - - luaserver_data *lsd = (class luaserver_data *)arg; - - CLuaInstance lua; - std::string result_code; - std::string result_string; - std::string error_string; - lua.runScript(lsd->script.c_str(), &lsd->argv, &result_code, &result_string, &error_string); - size_t result_code_len = result_code.length() + 1; - size_t result_string_len = result_string.length() + 1; - size_t error_string_len = error_string.length() + 1; - size_t size = result_code_len + result_string_len + error_string_len; - char result[size + sizeof(size)]; - char *rp = result; - memcpy(rp, &size, sizeof(size)); - rp += sizeof(size); - size += sizeof(size); - memcpy(rp, result_code.c_str(), result_code_len); - rp += result_code_len; - memcpy(rp, result_string.c_str(), result_string_len); - rp += result_string_len; - memcpy(rp, error_string.c_str(), error_string_len); - rp += error_string_len; - CBasicServer::send_data(lsd->fd, result, size); - - delete lsd; - luaserver_lock(); - luaserver_count--; - if (!luaserver_count) - sem_post(&CNeutrinoApp::getInstance()->lua_may_run); - luaserver_unlock(); - pthread_exit(NULL); -} - -static bool luaserver_parse_command(CBasicMessage::Header &rmsg __attribute__((unused)), int connfd) -{ - size_t size; - - if (!CBasicServer::receive_data(connfd, &size, sizeof(size))) { - fprintf(stderr, "%s %s %d: receive_data failed\n", __FILE__, __func__, __LINE__); - return true; - } - char data[size]; - if (!CBasicServer::receive_data(connfd, data, size)) { - fprintf(stderr, "%s %s %d: receive_data failed\n", __FILE__, __func__, __LINE__); - return true; - } - if (data[size - 1]) { - fprintf(stderr, "%s %s %d: unterminated string\n", __FILE__, __func__, __LINE__); - return true; - } - std::string luascript(LUAPLUGINDIR "/"); - luascript += data; - luascript += ".lua"; - if (access(luascript, R_OK)) { - fprintf(stderr, "%s %s %d: %s not found\n", __FILE__, __func__, __LINE__, luascript.c_str()); - const char *result_code = "-1"; - const char *result_string = ""; - std::string error_string = luascript + " not found\n"; - size_t result_code_len = strlen(result_code) + 1; - size_t result_string_len = strlen(result_string) + 1; - size_t error_string_len = strlen(error_string.c_str()) + 1; - size = result_code_len + result_string_len + error_string_len; - char result[size + sizeof(size)]; - char *rp = result; - memcpy(rp, &size, sizeof(size)); - rp += sizeof(size); - size += sizeof(size); - memcpy(rp, result_code, result_code_len); - rp += result_code_len; - memcpy(rp, result_string, result_string_len); - rp += result_string_len; - memcpy(rp, error_string.c_str(), error_string_len); - rp += error_string_len; - CBasicServer::send_data(connfd, result, size); - return true; - } - luaserver_data *lsd = new luaserver_data(connfd, luascript); - char *datap = data; - while (size > 0) { - lsd->argv.push_back(std::string(datap)); - size_t len = strlen(datap) + 1; - datap += len; - size -= len; - } - - luaserver_lock(); - if (!luaserver_count) - sem_wait(&CNeutrinoApp::getInstance()->lua_may_run); - luaserver_unlock(); - - pthread_t thr; - pthread_create (&thr, NULL, luaserver_thread, (void *) lsd); - pthread_detach(thr); - - return true; -} - -void *luaserver_main_thread(void *) { - set_threadname(__func__); - - CBasicServer server; - if (!server.prepare(LUACLIENT_UDS_NAME)) { - fprintf(stderr, "%s %s %d: prepare failed\n", __FILE__, __func__, __LINE__); - pthread_exit(NULL); - } - - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); - pthread_mutex_init(&luaserver_mutex, &attr); - - server.run(luaserver_parse_command, LUACLIENT_VERSION); - pthread_exit(NULL); -} - -// -------------------------------------------------------------------------------- diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 514d03188..fe658c25b 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -130,6 +130,8 @@ #include #include +#include + int old_b_id = -1; CInfoClock *InfoClock; @@ -149,8 +151,6 @@ static bool timerd_thread_started = false; void * nhttpd_main_thread(void *data); -void * luaserver_main_thread(void *data); - //#define DISABLE_SECTIONSD extern cVideo * videoDecoder; @@ -1949,10 +1949,6 @@ TIMER_START(); if (!pthread_create (&nhttpd_thread, NULL, nhttpd_main_thread, (void *) NULL)) pthread_detach (nhttpd_thread); - pthread_t luaserver_thread; - pthread_create (&luaserver_thread, NULL, luaserver_main_thread, (void *) NULL); - pthread_detach(luaserver_thread); - CStreamManager::getInstance()->Start(); #ifndef DISABLE_SECTIONSD @@ -2112,19 +2108,13 @@ void CNeutrinoApp::RealRun(CMenuWidget &mainMenu) //cCA::GetInstance()->Ready(true); - sem_init(&lua_may_run, 0, 0); - sem_init(&lua_did_run, 0, 0); + CLuaServer *luaServer = CLuaServer::getInstance(); while( true ) { - sem_post(&lua_may_run); + luaServer->UnBlock(); g_RCInput->getMsg(&msg, &data, 100, ((g_settings.mode_left_right_key_tv == SNeutrinoSettings::VOLUME) && (g_RemoteControl->subChannels.size() < 1)) ? true : false); // 10 secs.. - sem_wait(&lua_may_run); - if (!sem_trywait(&lua_did_run)) { - if (msg != CRCInput::RC_timeout) - g_RCInput->postMsg(msg, data); - while (!sem_trywait(&lua_did_run)); + if (luaServer->Block(msg, data)) continue; - } if( ( mode == mode_tv ) || ( mode == mode_radio ) || ( mode == mode_webtv ) ) { if( (msg == NeutrinoMessages::SHOW_EPG) /* || (msg == CRCInput::RC_info) */ ) { @@ -4247,6 +4237,7 @@ bool CNeutrinoApp::StartPip(const t_channel_id channel_id) void CNeutrinoApp::Cleanup() { + CLuaServer::destroyInstance(); #ifdef EXIT_CLEANUP INFO("cleanup..."); printf("cleanup 10\n");fflush(stdout); @@ -4312,11 +4303,6 @@ void CNeutrinoApp::Cleanup() delete CEitManager::getInstance(); printf("cleanup 6\n");fflush(stdout); delete CVFD::getInstance(); - - // FIXME -- wait for luaserver threads to terminate? - sem_destroy(&lua_may_run); - sem_destroy(&lua_did_run); - #ifdef __UCLIBC__ malloc_stats(NULL); #else diff --git a/src/neutrino.h b/src/neutrino.h index 82901f321..70c59772a 100644 --- a/src/neutrino.h +++ b/src/neutrino.h @@ -34,7 +34,6 @@ #define __neutrino__ #include -#include #include #include "driver/framebuffer.h" @@ -173,9 +172,6 @@ public: CChannelList *RADIOchannelList; CChannelList *channelList; - sem_t lua_may_run; - sem_t lua_did_run; - static CNeutrinoApp* getInstance(); void channelsInit(bool bOnly = false); diff --git a/src/system/Makefile.am b/src/system/Makefile.am index 383330fad..2ceca86d1 100644 --- a/src/system/Makefile.am +++ b/src/system/Makefile.am @@ -39,6 +39,7 @@ libneutrino_system_a_SOURCES = \ hddstat.cpp \ httptool.cpp \ lastchannel.cpp \ + luaserver.cpp \ localize.cpp \ helpers.cpp \ ping.cpp \ diff --git a/src/system/luaserver.cpp b/src/system/luaserver.cpp new file mode 100644 index 000000000..364a4fd55 --- /dev/null +++ b/src/system/luaserver.cpp @@ -0,0 +1,252 @@ +/* + (C)2014 by martii + + License: GPL + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#if 0 +For testing try: + +cat < /lib/tuxbox/luaplugins/test.lua +for i,v in ipairs(arg) do + print(tostring(i) .. "\t" .. tostring(v)) +end +return "ok" +EOT + +followed by luaclient test a b c d +#endif + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "luaserver.h" + +static CLuaServer *instance = NULL; + +CLuaServer *CLuaServer::getInstance() +{ + if (!instance) + instance = new CLuaServer(); + return instance; +} + +void CLuaServer::destroyInstance() +{ + if (instance) { + delete instance; + instance = NULL; + } +} + +CLuaServer::CLuaServer() +{ + count = 0; + + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK_NP); + pthread_mutex_init(&mutex, &attr); + + sem_init(&may_run, 0, 0); + sem_init(&did_run, 0, 0); + + pthread_create (&thr, NULL, luaserver_main_thread, (void *) NULL); +} + +CLuaServer::~CLuaServer() +{ + sem_destroy(&may_run); + sem_destroy(&did_run); + instance = NULL; + pthread_join(thr, NULL); +} + +void CLuaServer::UnBlock() +{ + sem_post(&may_run); +} + +bool CLuaServer::Block(const neutrino_msg_t msg, const neutrino_msg_data_t data) +{ + sem_wait(&may_run); + if (!sem_trywait(&did_run)) { + if (msg != CRCInput::RC_timeout) + g_RCInput->postMsg(msg, data); + while (!sem_trywait(&did_run)); + return true; + } + return false; +} + +class luaserver_data +{ + public: + int fd; + std::vector argv; + std::string script; + + luaserver_data(int _fd, std::string &_script) { + fd = dup(_fd); + fcntl(fd, F_SETFD, FD_CLOEXEC); + script = _script; + } + ~luaserver_data(void) { + close(fd); + } +}; + +void CLuaServer::Lock(void) +{ + pthread_mutex_lock(&instance->mutex); +} + +void CLuaServer::UnLock(void) +{ + pthread_mutex_unlock(&instance->mutex); +} + +void *CLuaServer::luaserver_thread(void *arg) { + set_threadname(__func__); + Lock(); + instance->count++; + UnLock(); + sem_post(&instance->did_run); + + luaserver_data *lsd = (class luaserver_data *)arg; + + CLuaInstance lua; + std::string result_code; + std::string result_string; + std::string error_string; + lua.runScript(lsd->script.c_str(), &lsd->argv, &result_code, &result_string, &error_string); + size_t result_code_len = result_code.length() + 1; + size_t result_string_len = result_string.length() + 1; + size_t error_string_len = error_string.length() + 1; + size_t size = result_code_len + result_string_len + error_string_len; + char result[size + sizeof(size)]; + char *rp = result; + memcpy(rp, &size, sizeof(size)); + rp += sizeof(size); + size += sizeof(size); + memcpy(rp, result_code.c_str(), result_code_len); + rp += result_code_len; + memcpy(rp, result_string.c_str(), result_string_len); + rp += result_string_len; + memcpy(rp, error_string.c_str(), error_string_len); + rp += error_string_len; + CBasicServer::send_data(lsd->fd, result, size); + + delete lsd; + Lock(); + instance->count--; + if (!instance->count) + sem_post(&instance->may_run); + UnLock(); + pthread_exit(NULL); +} + +bool CLuaServer::luaserver_parse_command(CBasicMessage::Header &rmsg __attribute__((unused)), int connfd) +{ + size_t size; + + if (!CBasicServer::receive_data(connfd, &size, sizeof(size))) { + fprintf(stderr, "%s %s %d: receive_data failed\n", __FILE__, __func__, __LINE__); + return true; + } + char data[size]; + if (!CBasicServer::receive_data(connfd, data, size)) { + fprintf(stderr, "%s %s %d: receive_data failed\n", __FILE__, __func__, __LINE__); + return true; + } + if (data[size - 1]) { + fprintf(stderr, "%s %s %d: unterminated string\n", __FILE__, __func__, __LINE__); + return true; + } + std::string luascript(LUAPLUGINDIR "/"); + luascript += data; + luascript += ".lua"; + if (access(luascript, R_OK)) { + fprintf(stderr, "%s %s %d: %s not found\n", __FILE__, __func__, __LINE__, luascript.c_str()); + const char *result_code = "-1"; + const char *result_string = ""; + std::string error_string = luascript + " not found\n"; + size_t result_code_len = strlen(result_code) + 1; + size_t result_string_len = strlen(result_string) + 1; + size_t error_string_len = strlen(error_string.c_str()) + 1; + size = result_code_len + result_string_len + error_string_len; + char result[size + sizeof(size)]; + char *rp = result; + memcpy(rp, &size, sizeof(size)); + rp += sizeof(size); + size += sizeof(size); + memcpy(rp, result_code, result_code_len); + rp += result_code_len; + memcpy(rp, result_string, result_string_len); + rp += result_string_len; + memcpy(rp, error_string.c_str(), error_string_len); + rp += error_string_len; + CBasicServer::send_data(connfd, result, size); + return true; + } + luaserver_data *lsd = new luaserver_data(connfd, luascript); + char *datap = data; + while (size > 0) { + lsd->argv.push_back(std::string(datap)); + size_t len = strlen(datap) + 1; + datap += len; + size -= len; + } + + Lock(); + if (!instance->count) + sem_wait(&instance->may_run); + UnLock(); + + pthread_t thr; + pthread_create (&thr, NULL, luaserver_thread, (void *) lsd); + pthread_detach(thr); + + return true; +} + +void *CLuaServer::luaserver_main_thread(void *) { + set_threadname(__func__); + + CBasicServer server; + if (!server.prepare(LUACLIENT_UDS_NAME)) { + fprintf(stderr, "%s %s %d: prepare failed\n", __FILE__, __func__, __LINE__); + pthread_exit(NULL); + } + + + server.run(luaserver_parse_command, LUACLIENT_VERSION); + pthread_exit(NULL); +} diff --git a/src/system/luaserver.h b/src/system/luaserver.h new file mode 100644 index 000000000..972066060 --- /dev/null +++ b/src/system/luaserver.h @@ -0,0 +1,50 @@ +/* + (C)2014 by martii + + License: GPL + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __LUASERVER_H__ +#define __LUASERVER_H__ +#include +#include +#include + +class CLuaServer +{ + private: + int count; + pthread_t thr; + pthread_mutex_t mutex; + + static void *luaserver_thread(void *arg); + static void *luaserver_main_thread(void *); + static bool luaserver_parse_command(CBasicMessage::Header &rmsg, int connfd); + static void Lock(); + static void UnLock(); + CLuaServer(); + ~CLuaServer(); + public: + sem_t may_run; + sem_t did_run; + + void UnBlock(); + bool Block(const neutrino_msg_t msg, const neutrino_msg_data_t data); + static CLuaServer *getInstance(); + static void destroyInstance(); +}; +#endif