[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Multiple Lua Threads, __gc crash accessing "dead" thread
- From: Francisco Olarte <folarte@...>
- Date: Wed, 13 Sep 2017 16:26:05 +0200
On Wed, Sep 13, 2017 at 4:02 PM, ThePhD <jm3689@columbia.edu> wrote:
> Observe the following complete, compile-able (and mostly C) code, which
> stores a simple "luaL_ref" wrapper in a struct named "co_test" and links up
> a simple creation method ("new") and a simple deletion method ("__gc"):
...
> void co_test_destroy(co_test* p) {
> luaL_unref(p->L, LUA_REGISTRYINDEX, p->ref);
> p->ref = 0;
> p->L = NULL;
> }
...
> int co_test___gc(lua_State* L) {
> co_test* p = (co_test*)lua_touserdata(L, 1);
>
> co_test_destroy(p);
>
> return 0;
> }
...
> In "co_test_destroy", the code segfaults (g++, clang++) / "Read Access
> Violation" (VC++) when doing "luaL_unref" when this code executes. I found
> that the reason is that the "co" variable, which holds the coroutine and
> thread represented by the "L" that the "co_test" was created with, dies. If
> you do not explicitly "nil" the "co" variable in the Lua code, the
> thread/state that "co_test" is created with stays alive.
>
> This behavior is observable in Lua 5.3, 5.2 and 5.1 (but not with LuaJIT on
> VC++ and Windows, for some reason).
>
> I am unsure of how to get around this issue properly. I know in 5.2 and 5.3
> I can forcefully obtain the main thread's state and thusly avoid this
> problem altogether by just adjusting the "L" pointer in the "co_test_new"
> function. But I seem to be on an island for Lua 5.1.
Have you tried passing the lua_state from _gc to _destroy and using
that state to unref?
I mean:
void co_test_destroy(lua_State * L, co_test* p) { *** Extra parameter.
luaL_unref(L, LUA_REGISTRYINDEX, p->ref); *** Using parameter
instead of the data stored in p.
p->ref = 0;
p->L = NULL;
}
...
int co_test___gc(lua_State* L) {
co_test* p = (co_test*)lua_touserdata(L, 1);
co_test_destroy(L, p); *** Passing calling state, which must be ok.
return 0;
}
> Does anyone have any thoughts about this? Is this behavior desirable? Should
> I just ask my users to collect garbage before setting any coroutine/thread
> wrappers to "nil"?
Well, you are using a dead state, behaviour may be undesirable, but I
would call it expected.
Francisco Olarte