diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-04-12 13:25:25 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2012-04-12 13:25:25 -0300 |
commit | 1485ea2ee742779b0030152ebde92a8370518afa (patch) | |
tree | 28c819860d2d844626a1d6cdf324ca21f5147f8c | |
parent | b10dbe5c727eedace5c84addd0573bfa1b0c027a (diff) | |
download | lua-1485ea2ee742779b0030152ebde92a8370518afa.tar.gz lua-1485ea2ee742779b0030152ebde92a8370518afa.tar.bz2 lua-1485ea2ee742779b0030152ebde92a8370518afa.zip |
Finalizers may call functions from a dynamic library after
the library has been unloaded
-rw-r--r-- | bugs | 104 |
1 files changed, 102 insertions, 2 deletions
@@ -1880,8 +1880,8 @@ patch = [[ | |||
1880 | +++ lundump.c 2008/04/04 19:51:41 2.7.1.4 | 1880 | +++ lundump.c 2008/04/04 19:51:41 2.7.1.4 |
1881 | @@ -1,5 +1,5 @@ | 1881 | @@ -1,5 +1,5 @@ |
1882 | /* | 1882 | /* |
1883 | -** $Id: bugs,v 1.111 2011/10/21 19:34:23 roberto Exp roberto $ | 1883 | -** $Id: bugs,v 1.112 2012/01/20 18:32:13 roberto Exp roberto $ |
1884 | +** $Id: bugs,v 1.111 2011/10/21 19:34:23 roberto Exp roberto $ | 1884 | +** $Id: bugs,v 1.112 2012/01/20 18:32:13 roberto Exp roberto $ |
1885 | ** load precompiled Lua chunks | 1885 | ** load precompiled Lua chunks |
1886 | ** See Copyright Notice in lua.h | 1886 | ** See Copyright Notice in lua.h |
1887 | */ | 1887 | */ |
@@ -2520,6 +2520,106 @@ patch = [[ | |||
2520 | ]] | 2520 | ]] |
2521 | } | 2521 | } |
2522 | 2522 | ||
2523 | Bug{ | ||
2524 | what = [[Finalizers may call functions from a dynamic library after | ||
2525 | the library has been unloaded]], | ||
2526 | report = [[Josh Haberman, 2012/04/08]], | ||
2527 | since = [[5.1]], | ||
2528 | example = [[ | ||
2529 | local u = setmetatable({}, {__gc = function () foo() end}) | ||
2530 | local m = require 'mod' -- 'mod' may be any dynamic library written in C | ||
2531 | foo = m.foo -- 'foo' may be any function from 'mod' | ||
2532 | -- end program; it crashes | ||
2533 | ]], | ||
2534 | patch = [[ | ||
2535 | =================================================================== | ||
2536 | RCS file: RCS/loadlib.c,v | ||
2537 | retrieving revision 1.108 | ||
2538 | diff -r1.108 loadlib.c | ||
2539 | 95c95 | ||
2540 | < #define LIBPREFIX "LOADLIB: " | ||
2541 | --- | ||
2542 | > #define CLIBS "_CLIBS" | ||
2543 | 251,266c251,256 | ||
2544 | < | ||
2545 | < static void **ll_register (lua_State *L, const char *path) { | ||
2546 | < void **plib; | ||
2547 | < lua_pushfstring(L, "%s%s", LIBPREFIX, path); | ||
2548 | < lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ | ||
2549 | < if (!lua_isnil(L, -1)) /* is there an entry? */ | ||
2550 | < plib = (void **)lua_touserdata(L, -1); | ||
2551 | < else { /* no entry yet; create one */ | ||
2552 | < lua_pop(L, 1); /* remove result from gettable */ | ||
2553 | < plib = (void **)lua_newuserdata(L, sizeof(const void *)); | ||
2554 | < *plib = NULL; | ||
2555 | < luaL_setmetatable(L, "_LOADLIB"); | ||
2556 | < lua_pushfstring(L, "%s%s", LIBPREFIX, path); | ||
2557 | < lua_pushvalue(L, -2); | ||
2558 | < lua_settable(L, LUA_REGISTRYINDEX); | ||
2559 | < } | ||
2560 | --- | ||
2561 | > static void *ll_checkclib (lua_State *L, const char *path) { | ||
2562 | > void *plib; | ||
2563 | > lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | ||
2564 | > lua_getfield(L, -1, path); | ||
2565 | > plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ | ||
2566 | > lua_pop(L, 2); /* pop CLIBS table and 'plib' */ | ||
2567 | 270a261,270 | ||
2568 | > static void ll_addtoclib (lua_State *L, const char *path, void *plib) { | ||
2569 | > lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | ||
2570 | > lua_pushlightuserdata(L, plib); | ||
2571 | > lua_pushvalue(L, -1); | ||
2572 | > lua_setfield(L, -3, path); /* CLIBS[path] = plib */ | ||
2573 | > lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ | ||
2574 | > lua_pop(L, 1); /* pop CLIBS table */ | ||
2575 | > } | ||
2576 | > | ||
2577 | > | ||
2578 | 272,273c272,273 | ||
2579 | < ** __gc tag method: calls library's `ll_unloadlib' function with the lib | ||
2580 | < ** handle | ||
2581 | --- | ||
2582 | > ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib | ||
2583 | > ** handles in list CLIBS | ||
2584 | 276,278c276,281 | ||
2585 | < void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); | ||
2586 | < if (*lib) ll_unloadlib(*lib); | ||
2587 | < *lib = NULL; /* mark library as closed */ | ||
2588 | --- | ||
2589 | > int n = luaL_len(L, 1); | ||
2590 | > for (; n >= 1; n--) { /* for each handle, in reverse order */ | ||
2591 | > lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ | ||
2592 | > ll_unloadlib(lua_touserdata(L, -1)); | ||
2593 | > lua_pop(L, 1); /* pop handle */ | ||
2594 | > } | ||
2595 | 284,286c287,292 | ||
2596 | < void **reg = ll_register(L, path); | ||
2597 | < if (*reg == NULL) *reg = ll_load(L, path, *sym == '*'); | ||
2598 | < if (*reg == NULL) return ERRLIB; /* unable to load library */ | ||
2599 | --- | ||
2600 | > void *reg = ll_checkclib(L, path); /* check loaded C libraries */ | ||
2601 | > if (reg == NULL) { /* must load library? */ | ||
2602 | > reg = ll_load(L, path, *sym == '*'); | ||
2603 | > if (reg == NULL) return ERRLIB; /* unable to load library */ | ||
2604 | > ll_addtoclib(L, path, reg); | ||
2605 | > } | ||
2606 | 292c298 | ||
2607 | < lua_CFunction f = ll_sym(L, *reg, sym); | ||
2608 | --- | ||
2609 | > lua_CFunction f = ll_sym(L, reg, sym); | ||
2610 | 675,676c681,683 | ||
2611 | < /* create new type _LOADLIB */ | ||
2612 | < luaL_newmetatable(L, "_LOADLIB"); | ||
2613 | --- | ||
2614 | > /* create table CLIBS to keep track of loaded C libraries */ | ||
2615 | > luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); | ||
2616 | > lua_createtable(L, 0, 1); /* metatable for CLIBS */ | ||
2617 | 678a686 | ||
2618 | > lua_setmetatable(L, -2); | ||
2619 | ]] | ||
2620 | } | ||
2621 | |||
2622 | |||
2523 | --[=[ | 2623 | --[=[ |
2524 | Bug{ | 2624 | Bug{ |
2525 | what = [[ ]], | 2625 | what = [[ ]], |