lua-users home
lua-l archive

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


On Fri, Sep 16, 2011 at 2:06 PM, Gaspard Bucher <gaspard@teti.ch> wrote:
On Fri, Sep 16, 2011 at 12:30 PM, Gregory Bonik <gregory@bonik.org> wrote:
Gaspard Bucher wrote:
> From my understanding, when "foobar" or "thread" goes out of scope,
> the whole thing should be garbage collected. What is happening is that
> only the
> userdata inside foobar is collected but foobar is still a table. This
> table does not have any special mode.

I seems that the reason is the weak table. See the thread "Weak tables
and userdata finalization" by Mark Hamburg (2 Sep 2011).

When the last reference on 'foobar' is gone, it doesn't mean that the
whole island "thread->coroutine->foobar->udata" gets collected
immediately. Finalizer for 'udata' can be called earlier than the thread
is removed from the weak table. As a consequence, the scheduler can
resume the thread which uses an already finalized userdata.

As a solution to the problem, you can manually remove the thread from
the weak table in the foobar's finalizer (if foobar is a table and
you're using Lua 5.1, then you need to place the finalizer somewhere
else).

--Gregory





Hi Gregory,

I do not have any finalizers in the userdata. In fact, I used collectgarbage('stop') and explicitly called gc. The bug happens *after* the garbage collection cycle:
COLLECTING
-------------- ~D
-------------- ~lk.Thread
~foobar (printf in C++, does not access Lua)
DONE
table: 0x107756530 <lk.Debug: 0x0>

Right after DONE, the next coroutine is run by the scheduler and bang!

What *does* happen though is that the destruction of "foobar" does a close on the filedescriptor used by the scheduler for this coroutine:

1. foobar destruction ---> close(fd)
2. on next poll ---> fd
3. fd ---> wrap --> ... (should not reach the coroutine, but it does reach it).
4. co.resume
5. ==> bang!

Is this a bug in Lua ? I really do not see what I am doing wrong...


After some more investigation, I think this is some edge case bug because I do not see what is wrong with the following pattern:

I found that the bug happens when the userdata has it's own environment and when this environment contains a lua_thread which in turn contains foobar:


   +-------- stack -------------------+
   | |
   v |
foobar ---> udata ---> fenv ---> udata_thread
              ^ |
              | |
              +---------+

https://gist.github.com/1221403

The bug only appears when 'foobar' is in udata_thread's stack.


                                                               Gaspard