Forcing a Lua script to exit

后端 未结 10 953
长情又很酷
长情又很酷 2020-12-23 18:49

How do you end a long running Lua script?

I have two threads, one runs the main program and the other controls a user supplied Lua script. I need to kill the thread

相关标签:
10条回答
  • 2020-12-23 18:50

    possibly useless, but in the lua I use (luaplayer or PGELua), I exit with

    os.exit() 
    

    or

    pge.exit()
    
    0 讨论(0)
  • 2020-12-23 18:50

    session:destroy();

    Use this single line code on that where you are want to destroy lua script.

    0 讨论(0)
  • 2020-12-23 18:57

    I haven't found a way to cleanly kill a thread that is executing a long running lua script without relying on some intervention from the script itself. Here are some approaches I have taken in the past:

    1. If the script is long running it is most likely in some loop. The script can check the value of some global variable on each iteration. By setting this variable from outside of the script you can then terminate the thread.
    2. You can start the thread by using lua_resume. The script can then exit by using yield().
    3. You could provide your own implementation of pcall that checks for a specific type of error. The script could then call error() with a custom error type that your version of pcall could watch for:

      function()
          local there_is_an_error = do_something()
          if (there_is_an_error) then
              error({code = 900, msg = "Custom error"})
          end
      end
      
    0 讨论(0)
  • 2020-12-23 18:58

    It seems like you could terminate the thread externally (from your main thread) since the lua script is user supplied and you can't signal it to exit.

    If that isn't an option, you could try the debug API. You could use lua_sethook to enable you to regain control assuming you have a way to gracefully terminate your thread in the hook.

    0 讨论(0)
  • 2020-12-23 18:59

    You might wanna take look at https://github.com/amilamad/preemptive-task-scheduler-for-lua project. its preemptive scheduler for lua. It uses a lua_yeild function inside the hook. So you can suspend your lua thread. It also uses longjmp inside but its is much safer.

    0 讨论(0)
  • 2020-12-23 18:59
    lua_KFunction cont(lua_State* L);
    int my_yield_with_res(lua_State* L, int res) {
        cout << " my_yield_with_res \n" << endl;
        return lua_yieldk(L, 0, lua_yield(L, res), cont(L));/* int lua_yieldk(lua_State * L, int res, lua_KContext ctx, lua_KFunction k);
        Приостанавливает выполнение сопрограммы(поток). Когда функция C вызывает lua_yieldk, работающая
        сопрограмма приостанавливает свое выполнение и вызывает lua_resume, которая начинает возврат данной сопрограммы.
        Параметр res - это число значений из стека, которые будут переданы в качестве результатов в lua_resume.
        Когда сопрограмма снова возобновит выполнение, Lua вызовет заданную функцию продолжения k для продолжения выполнения
        приостановленной C функции(смотрите §4.7). */
    };
    int hookFunc(lua_State* L, lua_Debug* ar) {
        cout << " hookFunc \n" << endl;
        return my_yield_with_res(L, 0);// хук./
    };
    
    lua_KFunction cont(lua_State* L) {// функция продолжения.
        cout << " hooh off \n" << endl;
        lua_sethook(L, (lua_Hook)hookFunc, LUA_MASKCOUNT, 0);// отключить хук foo.
        return 0;
    };
    
    struct Func_resume {
        Func_resume(lua_State* L, const char* funcrun, unsigned int Args) : m_L(L), m_funcrun(funcrun), m_Args(Args) {}
        //имена функций, кол-во агрументов.
    private:
        void func_block(lua_State* L, const char* functionName, unsigned int Count, unsigned int m_Args) {
            lua_sethook(m_L, (lua_Hook)hookFunc, LUA_MASKCOUNT, Count); //вызов функции с заданной паузой.
            if (m_Args == 0) {
                lua_getglobal(L, functionName);// получить имя функции.
                lua_resume(L, L, m_Args);
            }
            if (m_Args != 0) {
                int size = m_Args + 1;
                lua_getglobal(L, functionName);
                for (int i = 1; i < size; i++) {
                    lua_pushvalue(L, i);
                }
                lua_resume(L, L, m_Args);
            }
        };
    public:
        void Update(float dt) {
            unsigned int Count = dt * 100.0;// Время работы потока.
            func_block(m_L, m_funcrun, Count, m_Args);
        };
        ~Func_resume() {}
    private:
        lua_State* m_L;
        const char* m_funcrun; // имя функции.
        unsigned int m_Count;// число итерации.
        unsigned int m_Args;
    };
    
    const char* LUA = R"(
    function main(y) 
      --print(" func main arg, a = ".. a.." y = ".. y)      
    for i = 1, y do
      print(" func main count = ".. i)      
      end
    end
    )";
    int main(int argc, char* argv[]) {
        lua_State* L = luaL_newstate();/*Функция создает новое Lua состояние. */
        luaL_openlibs(L);
        luaL_dostring(L, LUA);
        //..pushlua(L, 12);
        pushlua(L, 32);
        //do {
            Func_resume func_resume(L, "main", 2);
            func_resume.Update(1.7);
            lua_close(L);
    //  } while (LUA_OK != lua_status(L)); // Пока  поток не завершен.
    
    
        return 0;
    };
    
    0 讨论(0)
提交回复
热议问题