diff options
Diffstat (limited to '')
| -rw-r--r-- | loadlib.c | 75 |
1 files changed, 40 insertions, 35 deletions
| @@ -307,6 +307,16 @@ static void setpath (lua_State *L, const char *fieldname, | |||
| 307 | 307 | ||
| 308 | 308 | ||
| 309 | /* | 309 | /* |
| 310 | ** External strings created by DLLs may need the DLL code to be | ||
| 311 | ** deallocated. This implies that a DLL can only be unloaded after all | ||
| 312 | ** its strings were deallocated. To ensure that, we create a 'library | ||
| 313 | ** string' to represent each DLL, and when this string is deallocated | ||
| 314 | ** it closes its corresponding DLL. | ||
| 315 | ** (The string itself is irrelevant; its userdata is the DLL pointer.) | ||
| 316 | */ | ||
| 317 | |||
| 318 | |||
| 319 | /* | ||
| 310 | ** return registry.CLIBS[path] | 320 | ** return registry.CLIBS[path] |
| 311 | */ | 321 | */ |
| 312 | static void *checkclib (lua_State *L, const char *path) { | 322 | static void *checkclib (lua_State *L, const char *path) { |
| @@ -320,34 +330,41 @@ static void *checkclib (lua_State *L, const char *path) { | |||
| 320 | 330 | ||
| 321 | 331 | ||
| 322 | /* | 332 | /* |
| 323 | ** registry.CLIBS[path] = plib -- for queries | 333 | ** Deallocate function for library strings. |
| 324 | ** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries | 334 | ** Unload the DLL associated with the string being deallocated. |
| 325 | */ | 335 | */ |
| 326 | static void addtoclib (lua_State *L, const char *path, void *plib) { | 336 | static void *freelib (void *ud, void *ptr, size_t osize, size_t nsize) { |
| 327 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | 337 | /* string itself is irrelevant and static */ |
| 328 | lua_pushlightuserdata(L, plib); | 338 | (void)ptr; (void)osize; (void)nsize; |
| 329 | lua_pushvalue(L, -1); | 339 | lsys_unloadlib(ud); /* unload library represented by the string */ |
| 330 | lua_setfield(L, -3, path); /* CLIBS[path] = plib */ | 340 | return NULL; |
| 331 | lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ | ||
| 332 | lua_pop(L, 1); /* pop CLIBS table */ | ||
| 333 | } | 341 | } |
| 334 | 342 | ||
| 335 | 343 | ||
| 336 | /* | 344 | /* |
| 337 | ** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib | 345 | ** Create a library string that, when deallocated, will unload 'plib' |
| 338 | ** handles in list CLIBS | ||
| 339 | */ | 346 | */ |
| 340 | static int gctm (lua_State *L) { | 347 | static void createlibstr (lua_State *L, void *plib) { |
| 341 | lua_Integer n = luaL_len(L, 1); | 348 | static const char dummy[] = /* common long body for all library strings */ |
| 342 | for (; n >= 1; n--) { /* for each handle, in reverse order */ | 349 | "01234567890123456789012345678901234567890123456789"; |
| 343 | lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ | 350 | lua_pushexternalstring(L, dummy, sizeof(dummy) - 1, freelib, plib); |
| 344 | lsys_unloadlib(lua_touserdata(L, -1)); | ||
| 345 | lua_pop(L, 1); /* pop handle */ | ||
| 346 | } | ||
| 347 | return 0; | ||
| 348 | } | 351 | } |
| 349 | 352 | ||
| 350 | 353 | ||
| 354 | /* | ||
| 355 | ** registry.CLIBS[path] = plib -- for queries. | ||
| 356 | ** Also create a reference to strlib, so that the library string will | ||
| 357 | ** only be collected when registry.CLIBS is collected. | ||
| 358 | */ | ||
| 359 | static void addtoclib (lua_State *L, const char *path, void *plib) { | ||
| 360 | lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); | ||
| 361 | lua_pushlightuserdata(L, plib); | ||
| 362 | lua_setfield(L, -2, path); /* CLIBS[path] = plib */ | ||
| 363 | createlibstr(L, plib); | ||
| 364 | luaL_ref(L, -2); /* keep library string in CLIBS */ | ||
| 365 | lua_pop(L, 1); /* pop CLIBS table */ | ||
| 366 | } | ||
| 367 | |||
| 351 | 368 | ||
| 352 | /* error codes for 'lookforfunc' */ | 369 | /* error codes for 'lookforfunc' */ |
| 353 | #define ERRLIB 1 | 370 | #define ERRLIB 1 |
| @@ -361,8 +378,8 @@ static int gctm (lua_State *L) { | |||
| 361 | ** Then, if 'sym' is '*', return true (as library has been loaded). | 378 | ** Then, if 'sym' is '*', return true (as library has been loaded). |
| 362 | ** Otherwise, look for symbol 'sym' in the library and push a | 379 | ** Otherwise, look for symbol 'sym' in the library and push a |
| 363 | ** C function with that symbol. | 380 | ** C function with that symbol. |
| 364 | ** Return 0 and 'true' or a function in the stack; in case of | 381 | ** Return 0 with 'true' or a function in the stack; in case of |
| 365 | ** errors, return an error code and an error message in the stack. | 382 | ** errors, return an error code with an error message in the stack. |
| 366 | */ | 383 | */ |
| 367 | static int lookforfunc (lua_State *L, const char *path, const char *sym) { | 384 | static int lookforfunc (lua_State *L, const char *path, const char *sym) { |
| 368 | void *reg = checkclib(L, path); /* check loaded C libraries */ | 385 | void *reg = checkclib(L, path); /* check loaded C libraries */ |
| @@ -704,21 +721,9 @@ static void createsearcherstable (lua_State *L) { | |||
| 704 | } | 721 | } |
| 705 | 722 | ||
| 706 | 723 | ||
| 707 | /* | ||
| 708 | ** create table CLIBS to keep track of loaded C libraries, | ||
| 709 | ** setting a finalizer to close all libraries when closing state. | ||
| 710 | */ | ||
| 711 | static void createclibstable (lua_State *L) { | ||
| 712 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ | ||
| 713 | lua_createtable(L, 0, 1); /* create metatable for CLIBS */ | ||
| 714 | lua_pushcfunction(L, gctm); | ||
| 715 | lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ | ||
| 716 | lua_setmetatable(L, -2); | ||
| 717 | } | ||
| 718 | |||
| 719 | |||
| 720 | LUAMOD_API int luaopen_package (lua_State *L) { | 724 | LUAMOD_API int luaopen_package (lua_State *L) { |
| 721 | createclibstable(L); | 725 | luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); /* create CLIBS table */ |
| 726 | lua_pop(L, 1); /* will not use it now */ | ||
| 722 | luaL_newlib(L, pk_funcs); /* create 'package' table */ | 727 | luaL_newlib(L, pk_funcs); /* create 'package' table */ |
| 723 | createsearcherstable(L); | 728 | createsearcherstable(L); |
| 724 | /* set paths */ | 729 | /* set paths */ |
