[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Condition of the lua_State in __gc handler after call to lua_close() ?
- From: Carsten Fuchs <CarstenFuchs@...>
- Date: Wed, 09 Apr 2008 20:05:43 +0200
Dear list,
when a call to lua_close() triggers calls to the the __gc handlers/callbacks, in what condition is
the Lua state (given as the lua_State* parameter to the __gc handler) at that time?
That is, will a global variable that held the userdata for which the __gc handler is currently being
called still be accessible "normally" as in any other C callback?
More importantly, if there is *another* userdata instance as a value in the globals table or in the
registry, and I overwrite it by assigning nil to the same index, is that a valid operation to do in
the __gc handler?
I'm asking this because I'm binding C++ objects to Lua using tables, where the tables contain the
userdata at a special index. Because I sometimes need to keep instances of such objects in pure C++
code (Example: w=newWindow(); gui:SetRootWindow(w); w=nil; ) I have to prevent Lua from garbage
collecting them early.
Thus, I "anchor" such objects (w in the example) by putting them into the registry, employing a
reference-counting scheme on the C++ side: When the first reference is created, the anchor in the
registry is established, when the last reference is gone (count drops to zero), the anchor in the
registry is overwritten with nil.
The "problem" is that my windows can have child windows (Example: w:AddChild(newWindow()); ), which
means that they too establish reference-counted anchors in the C++ instance.
Thus, when a window is destroyed, also its references to its parent and children are destroyed. If
one of these references was the last reference to a child window, it would try to un-anchor the
child window in the registry again by overwriting it with nil.
I got all of this working, and I don't think that there is a problem when that happens in a normal
run of the garbage collector. (In fact, my current implementation as described above suffers from
the problem that a hierarchy of windows is never garbage collected, because there is always the
anchor in the registry. I'll fix this soon, and it is not related to my question.)
However, when the forced shutdown by a call to lua_close() occurs, this sequence of events can occur:
a) The __gc handler is called for a window,
b) which deletes it's C++ instance.
c) The destructor of the C++ instance removes all references to the parent and children.
d) If a reference count drops to zero during step "c)", because e.g. nobody else refers to a child,
the reference will attempt to un-anchor the child from the registry, by overwriting it with nil.
I've never experienced crashes or memory corruption with this, but I still wonder if this is a valid
action?
Many thanks and best regards,
Carsten
--
http://www.Ca3D-Engine.de
Multi-Player, Multi-Platform, Real-Time 3D Action