Unset object's metatable in __gc
Run the following code: do local d local f = function() d.visible = true end if _VERSION >= "Lua 5.2" then setmetatable({}, { __gc = f }) else getmetatable(newproxy(true)).__gc = f end d = drawin({}) end collectgarbage("collect") Awesome will segfault. The reason for this is that after the above code ran, all variables in it are unreferenced and will be garbage-collected at the next sweep phase. Lua runs garbage collectors in the inverse order that their corresponding objects were "marked" which means for the above code that the drawin's garbage collector will run before function f runs. So the code will access the drawin after its destructor already ran. Obviously, awesome's C code does not expect nor correctly deal with this situation and was dereferencing a NULL pointer. To fix this, this commit "unsets" the metatable of a userdata object when it is being garbage collected. Since the type of a userdata is inferred via its metatable, the object will no longer be accepted by luaA_toudata(). For the above code this will result in an unhelpful error message saying that something tried to index a userdata, but userdata cannot be indexed. At least we no longer crash and the traceback of the error will hopefully point at some __gc metamethod which should be enough of a hint to figure out the problem. Thanks-to: http://blog.reverberate.org/2014/06/beware-of-lua-finalizers-in-c-modules.html Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
4bea4554fb
commit
1408e8b952
|
@ -179,6 +179,11 @@ luaA_class_gc(lua_State *L)
|
||||||
for(; class; class = class->parent)
|
for(; class; class = class->parent)
|
||||||
if(class->collector)
|
if(class->collector)
|
||||||
class->collector(item);
|
class->collector(item);
|
||||||
|
/* Unset its metatable so that e.g. luaA_toudata() will no longer accept
|
||||||
|
* this object. This is needed since other __gc methods can still use this.
|
||||||
|
*/
|
||||||
|
lua_newtable(L);
|
||||||
|
lua_setmetatable(L, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue