aboutsummaryrefslogtreecommitdiff
path: root/loadlib.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--loadlib.c75
1 files changed, 40 insertions, 35 deletions
diff --git a/loadlib.c b/loadlib.c
index 5f0c1702..8d2e68e2 100644
--- a/loadlib.c
+++ b/loadlib.c
@@ -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*/
312static void *checkclib (lua_State *L, const char *path) { 322static 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*/
326static void addtoclib (lua_State *L, const char *path, void *plib) { 336static 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*/
340static int gctm (lua_State *L) { 347static void createlibstr (lua_State *L, void *plib) {
341 lua_Integer n = luaL_len(L, 1); 348 /* common content for all library strings */
342 for (; n >= 1; n--) { /* for each handle, in reverse order */ 349 static const char dummy[] = "01234567890";
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*/
359static 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*/
367static int lookforfunc (lua_State *L, const char *path, const char *sym) { 384static 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*/
711static 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
720LUAMOD_API int luaopen_package (lua_State *L) { 724LUAMOD_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 */