[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: coroutine.resume() crash
- From: John Dunn <John.Dunn@...>
- Date: Mon, 12 Sep 2022 22:06:30 +0000
> From: Gé Weijers <ge@weijers.org>
> You used the word 'asynchronous' in your first email. I hope you're not trying to (for instance) call into
> the Lua interpreter from a signal handler or another thread, because that's going to royally mess up
> things and just end in tears😀. Lua is quite single-threaded by design.
>
It's all on a single thread. In my case I'm using libevent as a message loop to drive not only timers but also asynchronous network IO across multiple independent Lua states. I'm also not driving the event loop from within Lua - each Lua script is run once on load and after that it's all driven by various event handlers calling back into Lua when things happen - very similar to node.js model. I just get a callback from libevent when something happens ( ie a timer has expired, data is available on a socket, etc ) - I get context related to the timer ( in my case a pointer to a c++ timer object ) which is why I was storing the lua_State to use to call back into Lua when this happens.
What seems to work is -
1. when Lua starts I store the 'base' state using lua_setfield(L1, LUA_REGISTRYINDEX, .. ). Call this L1.
2. Timer.New() creates a new userdata - this can happen both in the main Lua state or a coroutine - call this L2. L2 is stored in a c++ data structure associated with the userdata
3. user assigns function to timer.EventHandler. This is via a metatable so I get a callback from Lua with some lua_State Lx. I store a reference to the function using this passed in state via luaL_ref
4. coroutine yields
5. at some point later libevent calls a callback on my c++ instance
6. this instance uses the stored L2 in the object to call lua_getfield(L2, LUA_REGISTRYINDEX, ..) to retrieve the L1
7. I look up the function via lua_rawgeti and call it using L1 as my lua_State
If coroutines aren't being use this still works - it just means L1 == L2.
While this works it's not clear to me this is safe and there are a couple of places where I have questions. For example, when I store(3) and retrieve(7) the function does it matter which lua_State is being used? Currently I'm using L2 to store and L1 to retrieve in my test and it's working - do all coroutines share the same LUA_REGISTRY which makes this possible? Also is there a better way then my scheme of stashing the base lua_State? I didn’t see a way to determine the base from an arbitrary lua_State in the c API.
John