Как я могу аккуратно завершить поток Lua?

Моя ситуация такова, что я использую Lua (C) API для выполнения скрипта, хранящегося в строке. Я бы хотел, чтобы пользователь мог прекратить выполнение сценария (это важно, если сценарий содержит бесконечный цикл), как я могу это сделать?

lua_State *Lua = lua_open();
char * code;
// Initialisation code
luaL_dostring(L, code);

person CiscoIPPhone    schedule 14.05.2009    source источник


Ответы (2)


Вы можете использовать ловушку для обратного вызова C каждый раз, когда lua выполняет строку скрипта. В этой функции перехвата вы можете проверить, хочет ли пользователь выйти, и вызвать lua_error, если он это сделал.

static bool ms_quit = false;

void IWantToQuit()
{
    ms_quit = true;
}

void LineHookFunc(lua_State *L, lua_Debug *ar)
{
    if(ar.event == LUA_HOOKLINE)
        if(ms_quit == true)
            luaL_error(L, "Too Many Lines Error");
}
//...

lua_State *Lua = lua_open();
char * code;
// Initialisation code
lua_sethook(Lua, &LineHookFunc, LUA_MASKLINE, 0);
luaL_dostring(L, code);
person Matthew Monaghan    schedule 14.05.2009
comment
Вы, вероятно, захотите либо вызвать luaL_error(L, "message"), либо поместить что-нибудь в стек Lua перед вызовом lua_error(L). - person Alexander Gladysh; 15.05.2009
comment
Спасибо, Александр, ответ отредактировал. Вы правы насчет однострочных циклов / бесконечных циклов в коде C, я признаю, что не вникал в сложности ситуации. - person Matthew Monaghan; 15.05.2009

Зацепить лески недостаточно. Этот код представляет собой одну строку, но повторяется бесконечно:

    while true do end

Вам нужно установить ловушку для подсчета инструкций. Если не ошибаюсь, это было бы

    lua_sethook(Lua, &LineHookFunc, LUA_MASKCOUNT, NUM_INSTRUCTIONS);

Вы хотите выбрать NUM_INSTRUCTIONS, чтобы оно не было слишком маленьким (или вы получили накладные расходы на производительность) и не слишком большим (или вы слишком долго ждали до остановки).

Соответствующую реализацию только для Lua см. В этой библиотеке.

Если вы хотите добавить дополнительную защиту от ненадежного кода Lua, поищите в Google "песочницу Lua" - это больше, чем просто предотвращение бесконечных циклов.

person Alexander Gladysh    schedule 14.05.2009
comment
Ты прав. Разве третий параметр не должен быть LUA_MASKCOUNT? Даже просто инструкции не идеальны - например, если код Lua выйдет из строя и вызовет длинную функцию C. Однако пока это подойдет для моих целей, спасибо. - person CiscoIPPhone; 15.05.2009
comment
Да, прости. Я добавил LUA_MASKCOUNT сейчас. - person Alexander Gladysh; 15.05.2009