diff --git a/src/gui/luainstance.cpp b/src/gui/luainstance.cpp index 3877bedd0..7ff3f88e2 100644 --- a/src/gui/luainstance.cpp +++ b/src/gui/luainstance.cpp @@ -480,6 +480,16 @@ void CLuaInstance::runScript(const char *fileName, const char *arg0, ...) args.clear(); } +static void abortHook(lua_State *lua, lua_Debug *) +{ + luaL_error(lua, "aborted"); +} + +void CLuaInstance::abortScript() +{ + lua_sethook(lua, &abortHook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + const luaL_Reg CLuaInstance::methods[] = { { "PaintBox", CLuaInstance::PaintBox }, diff --git a/src/gui/luainstance.h b/src/gui/luainstance.h index 8c926c4e7..8b2153074 100644 --- a/src/gui/luainstance.h +++ b/src/gui/luainstance.h @@ -176,6 +176,7 @@ public: CLuaInstance(); ~CLuaInstance(); void runScript(const char *fileName, std::vector *argv = NULL, std::string *result_code = NULL, std::string *result_string = NULL, std::string *error_string = NULL); + void abortScript(); // Example: runScript(fileName, "Arg1", "Arg2", "Arg3", ..., NULL); // Type of all parameters: const char* diff --git a/src/system/luaserver.cpp b/src/system/luaserver.cpp index 7bd499d4b..45521f656 100644 --- a/src/system/luaserver.cpp +++ b/src/system/luaserver.cpp @@ -114,7 +114,10 @@ bool CLuaServer::Block(const neutrino_msg_t msg, const neutrino_msg_data_t data) class luaserver_data { public: + CLuaInstance *lua; + bool died; int fd; + std::vector argv; std::string script; @@ -122,6 +125,7 @@ class luaserver_data fd = dup(_fd); fcntl(fd, F_SETFD, FD_CLOEXEC); script = _script; + died = false; } ~luaserver_data(void) { close(fd); @@ -138,6 +142,21 @@ void CLuaServer::UnLock(void) pthread_mutex_unlock(&mutex); } +void *CLuaServer::luaclient_watchdog(void *arg) { + set_threadname(__func__); + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + + luaserver_data *lsd = (class luaserver_data *)arg; + + struct pollfd pfd; + pfd.fd = lsd->fd; + pfd.events = pfd.revents = 0; + poll(&pfd, 1, -1); + lsd->lua->abortScript(); + lsd->died = true; + pthread_exit(NULL); +} + void *CLuaServer::luaserver_thread(void *arg) { set_threadname(__func__); Lock(); @@ -149,28 +168,35 @@ void *CLuaServer::luaserver_thread(void *arg) { luaserver_data *lsd = (class luaserver_data *)arg; + pthread_t wdthr; + pthread_create (&wdthr, NULL, luaclient_watchdog, (void *) lsd); + CLuaInstance lua; + lsd->lua = &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); - + pthread_cancel(wdthr); + pthread_join(wdthr, NULL); + if (!lsd->died) { + 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(); if (instance) { diff --git a/src/system/luaserver.h b/src/system/luaserver.h index 76d7bad8d..047132df0 100644 --- a/src/system/luaserver.h +++ b/src/system/luaserver.h @@ -32,6 +32,7 @@ class CLuaServer static void *luaserver_thread(void *arg); static void *luaserver_main_thread(void *); + static void *luaclient_watchdog(void *); static bool luaserver_parse_command(CBasicMessage::Header &rmsg, int connfd); static void Lock(); static void UnLock();