lua-users home
lua-l archive

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


Roberto Ierusalimschy wrote:

dlclose is called when you close the Lua state, calling lua_close.
The package loadlib creates a table in the registry, where it puts
all C packages it loads. We can see this table with this code:

   print(debug.getregistry()._CLIBS)    -- for Lua 5.4

This table has a metamethod __gc that dlclose's all libraries in that
table. As the table is in the registry, it is never collected, so that
it is called only when we close the Lua state.

Because this table is created and marked before we can load any C
module, it will be collected after the collection of any object
created by any C module.

This seems not to be true when closing a state and a finalizer creates a new object with a finalizer and calls os.exit(0, true). The os.exit call will append the new finalizer to the list tobefnz which already contains the finalizer for the _CLIBS table. With this the finalizer will run with all the c libs closed. The following code will crash with a Segmentation fault due to the closed c lib.

local tl = require "testlib"

setmetatable({},{__gc=function()
    -- Called when state is closed
    setmetatable({},{__gc=function()
        -- Called as last finalizer during os.exit(0, true)
        -- Here _CLIBS finalizer was already called
        tl.test()
    end})
    os.exit(0, true)
end})

where testlib can be replaced with any c lib but here is the version used:

#include "lua.h"
#include "lauxlib.h"

static int test(lua_State* L) {
    return 0;
}

static const struct luaL_Reg functions [] = {
    {"test", test},
    {NULL, NULL}
};

int luaopen_testlib(lua_State *L) {
    luaL_newlib(L, functions);
    return 1;
}

Regards,
Xmilia