From 85a3c1699c9587a9e952b4ab75b1c6c310ebebea Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 9 Jul 2025 14:40:36 -0300 Subject: New method to unload DLLs External strings created by DLLs may need the DLL code to be deallocated. This implies that a DLL can only be unloaded after all its strings were deallocated, which happen only after the run of all finalizers. To ensure that order, we create a 'library string' to represent each DLL and keep it locked. When this string is deallocated (after the deallocation of any string created by the DLL) it closes its corresponding DLL. --- testes/attrib.lua | 8 +++++++- testes/libs/lib22.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'testes') diff --git a/testes/attrib.lua b/testes/attrib.lua index d8b6e0f3..8a3462ea 100644 --- a/testes/attrib.lua +++ b/testes/attrib.lua @@ -300,6 +300,12 @@ else assert(_ENV.x == "lib2-v2" and _ENV.y == DC"lib2-v2") assert(lib2.id("x") == true) -- a different "id" implementation + for _, len in ipairs{0, 10, 39, 40, 41, 1000} do + local str = string.rep("a", len) + local str1 = lib2.newstr(str) + assert(str == str1) + end + -- test C submodules local fs, ext = require"lib1.sub" assert(_ENV.x == "lib1.sub" and _ENV.y == DC"lib1") @@ -447,7 +453,7 @@ do end --- test of large float/integer indices +-- test of large float/integer indices -- compute maximum integer where all bits fit in a float local maxint = math.maxinteger diff --git a/testes/libs/lib22.c b/testes/libs/lib22.c index 8e656502..b377cce5 100644 --- a/testes/libs/lib22.c +++ b/testes/libs/lib22.c @@ -1,3 +1,7 @@ +/* implementation for lib2-v2 */ + +#include + #include "lua.h" #include "lauxlib.h" @@ -8,8 +12,54 @@ static int id (lua_State *L) { } +struct STR { + void *ud; + lua_Alloc allocf; +}; + + +static void *t_freestr (void *ud, void *ptr, size_t osize, size_t nsize) { + struct STR *blk = (struct STR*)ptr - 1; + blk->allocf(blk->ud, blk, sizeof(struct STR) + osize, 0); + return NULL; +} + + +static int newstr (lua_State *L) { + size_t len; + const char *str = luaL_checklstring(L, 1, &len); + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + struct STR *blk = (struct STR*)allocf(ud, NULL, 0, + len + 1 + sizeof(struct STR)); + if (blk == NULL) { /* allocation error? */ + lua_pushliteral(L, "not enough memory"); + lua_error(L); /* raise a memory error */ + } + blk->ud = ud; blk->allocf = allocf; + memcpy(blk + 1, str, len + 1); + lua_pushexternalstring(L, (char *)(blk + 1), len, t_freestr, L); + return 1; +} + + +/* +** Create an external string and keep it in the registry, so that it +** will test that the library code is still available (to deallocate +** this string) when closing the state. +*/ +static void initstr (lua_State *L) { + lua_pushcfunction(L, newstr); + lua_pushstring(L, + "012345678901234567890123456789012345678901234567890123456789"); + lua_call(L, 1, 1); /* call newstr("0123...") */ + luaL_ref(L, LUA_REGISTRYINDEX); /* keep string in the registry */ +} + + static const struct luaL_Reg funcs[] = { {"id", id}, + {"newstr", newstr}, {NULL, NULL} }; @@ -18,6 +68,7 @@ LUAMOD_API int luaopen_lib2 (lua_State *L) { lua_settop(L, 2); lua_setglobal(L, "y"); /* y gets 2nd parameter */ lua_setglobal(L, "x"); /* x gets 1st parameter */ + initstr(L); luaL_newlib(L, funcs); return 1; } -- cgit v1.2.3-55-g6feb