lua-users home
lua-l archive

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

Hmmm.. I am nearly there. The function storage in the weak table works fine except... I cannot get hold of the function through the userdata's environment. Stack is

1: userdata (self)
2: function

    lua_getfenv(L, 1); // get environment for 'self'

    // env.callback = func
    lua_pushstring(L, "callback");
    lua_pushvalue(L, 2); // push func on top
    lua_settable(L, 3);

    // env.thread = thread
    lua_pushstring(L, "thread");
    lua_ = lua_newthread(L);
    lua_settable(L, 3);

    lua_pop(L, 1); // remove env table

If I replace the calls with luaL_ref(L, LUA_REGISTRYINDEX), the function and/or thread are no longer collected.

The test code holds the created threads by inserting them in a table:

function should.not_segfault()
  local threads = {}
  local functions = {}
  for i = 1,100 do
    table.insert(threads, rk.Thread(function()
      -- do nothing
      local j = 0
      while j < 10 do
        print(i, j)
        j = j + 1
    if i == 60 then
      print("collect ok.")

  for _, thread in ipairs(threads) do

  -- should not hang

Any idea what I am doing wrong ?

Gaspard (6am here: going to bed)

On Mon, Jan 3, 2011 at 3:40 AM, Gaspard Bucher <> wrote:
Storing the function in the environment table is one thing, but getting it back from C is another...

In order to get back to the function, I figured out this pattern:

0. On startup: create a weak table in the registry and store the location as a C global

1. push the weak table on top
lua_rawgeti(L, LUA_REGISTRYINDEX, g_weak_table_idx);

2. create reference
lua_pushvalue(L, -2);
int func_idx = luaL_ref(L, -1);

.. later ..
3. push weak table on top and get function
lua_rawgeti(L, LUA_REGISTRYINDEX, g_weak_table_idx);
lua_rawgeti(L, -1, func_idx);

Does this look ok ?

On Mon, Jan 3, 2011 at 3:01 AM, Gaspard Bucher <> wrote:
Hi Peter,

Thanks, this seems to be the correct way to handle my issue. I am looking at lua_getfenv and lua_setfenv and am not sure if this is how it is meant to be used:

-- callback function is at 1
-- rk.Thread userdata is at 2
lua_getfenv(L, 2);
lua_pushvalue(L, 1);
lua_pushstring(L, "callback");
lua_settable(L, -3);


On Mon, Jan 3, 2011 at 2:03 AM, Peter Odding <> wrote:
Hi Gaspard,

This is a difficult one: I have an OS thread that keeps hold of a
function in lua with luaL_ref(L, LUA_REGISTRYINDEX). But the OS thread
is created in Lua:

thread = rk.Thread(function()
  -- do this and that

After some time, the thread is garbage collected.

How can I remove the function from the registry ? I cannot call
luaL_unref in the rk.Thread destructor (segfault).

I'm not sure I have the full picture here, but why not give your thread userdata an environment table and then keep hold of the function in that environment table instead of in the global registry? Once your thread is garbage collected the environment table should be destroyed and any references in that table should automatically seize to exist.

 - Peter Odding