Исправления Lua и luabind для корректной работы с lua-потоками
Автор: Дмитрий Антонов
При активной работе в Lua с lua-потоками в связке с luabind, иногда может возникнуть неприятная проблема, связанная с тем, что lua-поток будет удален раньше, чем luabind-объекты, которые были созданы во время исполнения данного потока. Так как luabind хранит ссылки на необходимые ему lua-объекты ввиде пары lua_State* и индекса в таблице ссылок, то после удаления потока, lua_State* становится недейсвительным, и при попытке удаления luabind-объекта будет происходить обращения по этой недействительной ссылке.
Простейший код, в котором воссоздается данная ошибка:
int _tmain(int argc, _TCHAR* argv[]) { lua_State* L = luaL_newstate( ); luabind::open( L); luabind::module( L) [ luabind::class_<TestStruct>( "TestStruct") .def_readwrite( "x", &TestStruct::x) .def_readwrite( "y", &TestStruct::y), luabind::def( "func_get", &func_get), luabind::def( "func_set", &func_set) ]; lua_gc( L, LUA_GCSTOP, 0); lua_State* thread = lua_newthread( L); luaL_dostring( thread, "local val = func_get();\ local tmp = val.x;\ val.x = val.y;\ val.y = tmp;\ func_set(val);"); lua_pop( L, 1); lua_gc( L, LUA_GCCOLLECT, 0); return 0; }
Для того чтобы данной проблемы не возникало, необходимо внести некотрые исправления в исходный код Lua и luabind. Суть изменений — заставить сохранять luabind не ссылку на поток, в котором был создан объект, а ссылку на главный поток Luа, который не удаляется до окончания работы с Lua (более того, он всегда удаляется последним)
Исправления в Lua:
// ************************************************ // lua.h LUA_API lua_State * (lua_mainstate) ( lua_State *L); // ************************************************ // lapi.cpp LUA_API lua_State * lua_mainstate( lua_State *L) { return G( L)->mainthread; }
Исправления в luabind (luabind\detail\ref.hpp)
struct lua_reference { //........................... set - метод lua_reference void set(lua_State* L_) { reset( ); L = lua_globalstate( L_); // вот эту строку добавил и в следующей m_ref = ref( L_); // тут было m_ref = ref(L); }
При необходимости, можно внести аналогичные изменения в <luabind\handle.hpp>, который используется в luabind::object
2 февраля 2010 (Обновление: 11 апр 2010)
Комментарии [5]