lua-users home
lua-l archive

coroutine.resume() crash

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I am using Lua 5.3.2 and have some Lua modules that implement asynchronous callbacks. I was trying to wrap them in coroutines to make them act a little more like async/await and when I do that I get a crash
 ldo:636
 Exception thrown: read access violation
 ci->u.l.base was 0xFFFFFFFFFFFFFFFF
Here's example code that shows the problem - it crashes when running 'bad_lua'. Am I just misunderstanding how coroutines can operate?
 #include <lua/lua.hpp>
#include <string>
#include <iostream>
struct timer_t
{
 lua_State* L;
 int handler_index{ LUA_REFNIL };
 void trigger()
 {
 std::cout << __FUNCTION__ << std::endl;
 lua_rawgeti(L, LUA_REGISTRYINDEX, handler_index);
 lua_pcall(L, 0, 0, 0);
 }
};
timer_t* the_timer = nullptr;
static int timer_call_after(lua_State* L)
{
 std::cout << __FUNCTION__ << std::endl;
 timer_t** timer = (timer_t**)lua_newuserdata(L, sizeof(timer_t*));
 *timer = new timer_t();
 (*timer)->L = L;
 // store function
 lua_pushvalue(L, 1);
 (*timer)->handler_index = luaL_ref(L, LUA_REGISTRYINDEX);;
 // stash timer
 the_timer = *timer;
 return 0;
}
static const struct luaL_Reg timer_lib_methods[] =
{
 { "CallAfter", timer_call_after },
 {NULL,NULL}
};
void timer_init(lua_State* L)
{
 luaL_register(L, "Timer", timer_lib_methods);
}
const char* good_lua = R"XXX(
print("init good")
Timer.CallAfter(function() print("tick") end, time)
print("init good")
)XXX";
const char* bad_lua = R"XXX(
function wait(time)
 co = coroutine.running()
 Timer.CallAfter(function() coroutine.resume(co) end, time)
 return coroutine.yield()
end
function get_some_times()
 c = wait(2)
end
func = coroutine.wrap(get_some_times)
func()
print("init good")
)XXX";
void run(const char* code)
{
 lua_State* L = luaL_newstate();
 luaL_openlibs(L);
 timer_init(L);
 luaL_loadbuffer(L, code, strlen(code), "=");
 lua_pcall(L, 0, LUA_MULTRET, 0);
 // synthesize timer trigger
 the_timer->trigger();
}
int main(int argc, char** argv)
{
 std::cout << "running good code" << std::endl;
 run(good_lua);
 std::cout << "running bad code" << std::endl;
 run(bad_lua);
 return 0;
}

AltStyle によって変換されたページ (->オリジナル) /