Browse Source

Finalizers may call functions from a dynamic library after
the library has been unloaded

Roberto Ierusalimschy 13 years ago
parent
commit
1485ea2ee7
1 changed files with 102 additions and 2 deletions
  1. 102 2
      bugs

+ 102 - 2
bugs

@@ -1880,8 +1880,8 @@ patch = [[
 +++ lundump.c   2008/04/04 19:51:41     2.7.1.4
 @@ -1,5 +1,5 @@
  /*
--** $Id: bugs,v 1.111 2011/10/21 19:34:23 roberto Exp roberto $
-+** $Id: bugs,v 1.111 2011/10/21 19:34:23 roberto Exp roberto $
+-** $Id: bugs,v 1.112 2012/01/20 18:32:13 roberto Exp roberto $
++** $Id: bugs,v 1.112 2012/01/20 18:32:13 roberto Exp roberto $
  ** load precompiled Lua chunks
  ** See Copyright Notice in lua.h
  */
@@ -2520,6 +2520,106 @@ patch = [[
 ]]
 }
 
+Bug{
+what = [[Finalizers may call functions from a dynamic library after
+the library has been unloaded]],
+report = [[Josh Haberman, 2012/04/08]],
+since = [[5.1]],
+example = [[
+local u = setmetatable({}, {__gc = function () foo() end})
+local m = require 'mod'   -- 'mod' may be any dynamic library written in C
+foo = m.foo     -- 'foo' may be any function from 'mod'
+-- end program; it crashes
+]],
+patch = [[
+===================================================================
+RCS file: RCS/loadlib.c,v
+retrieving revision 1.108
+diff -r1.108 loadlib.c
+95c95
+< #define LIBPREFIX	"LOADLIB: "
+---
+> #define CLIBS		"_CLIBS"
+251,266c251,256
+< 
+< static void **ll_register (lua_State *L, const char *path) {
+<   void **plib;
+<   lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+<   lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */
+<   if (!lua_isnil(L, -1))  /* is there an entry? */
+<     plib = (void **)lua_touserdata(L, -1);
+<   else {  /* no entry yet; create one */
+<     lua_pop(L, 1);  /* remove result from gettable */
+<     plib = (void **)lua_newuserdata(L, sizeof(const void *));
+<     *plib = NULL;
+<     luaL_setmetatable(L, "_LOADLIB");
+<     lua_pushfstring(L, "%s%s", LIBPREFIX, path);
+<     lua_pushvalue(L, -2);
+<     lua_settable(L, LUA_REGISTRYINDEX);
+<   }
+---
+> static void *ll_checkclib (lua_State *L, const char *path) {
+>   void *plib;
+>   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+>   lua_getfield(L, -1, path);
+>   plib = lua_touserdata(L, -1);  /* plib = CLIBS[path] */
+>   lua_pop(L, 2);  /* pop CLIBS table and 'plib' */
+270a261,270
+> static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
+>   lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+>   lua_pushlightuserdata(L, plib);
+>   lua_pushvalue(L, -1);
+>   lua_setfield(L, -3, path);  /* CLIBS[path] = plib */
+>   lua_rawseti(L, -2, luaL_len(L, -2) + 1);  /* CLIBS[#CLIBS + 1] = plib */
+>   lua_pop(L, 1);  /* pop CLIBS table */
+> }
+> 
+> 
+272,273c272,273
+< ** __gc tag method: calls library's `ll_unloadlib' function with the lib
+< ** handle
+---
+> ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
+> ** handles in list CLIBS
+276,278c276,281
+<   void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
+<   if (*lib) ll_unloadlib(*lib);
+<   *lib = NULL;  /* mark library as closed */
+---
+>   int n = luaL_len(L, 1);
+>   for (; n >= 1; n--) {  /* for each handle, in reverse order */
+>     lua_rawgeti(L, 1, n);  /* get handle CLIBS[n] */
+>     ll_unloadlib(lua_touserdata(L, -1));
+>     lua_pop(L, 1);  /* pop handle */
+>   }
+284,286c287,292
+<   void **reg = ll_register(L, path);
+<   if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
+<   if (*reg == NULL) return ERRLIB;  /* unable to load library */
+---
+>   void *reg = ll_checkclib(L, path);  /* check loaded C libraries */
+>   if (reg == NULL) {  /* must load library? */
+>     reg = ll_load(L, path, *sym == '*');
+>     if (reg == NULL) return ERRLIB;  /* unable to load library */
+>     ll_addtoclib(L, path, reg);
+>   }
+292c298
+<     lua_CFunction f = ll_sym(L, *reg, sym);
+---
+>     lua_CFunction f = ll_sym(L, reg, sym);
+675,676c681,683
+<   /* create new type _LOADLIB */
+<   luaL_newmetatable(L, "_LOADLIB");
+---
+>   /* create table CLIBS to keep track of loaded C libraries */
+>   luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
+>   lua_createtable(L, 0, 1);  /* metatable for CLIBS */
+678a686
+>   lua_setmetatable(L, -2);
+]]
+}
+
+
 --[=[
 Bug{
 what = [[ ]],