lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Fri, Mar 19, 2010 at 8:49 AM, Roberto Ierusalimschy <roberto@inf.puc-rio.br> wrote:

> The thing is that when the Lua state is closed, the module is unloaded first
> and then the function 'module_cleanup' is (tried to be) called.

Is this what is happening or what you think it is happening?

Yes that is what is happening. However, when I set up to build a library with the minimal code to reproduce this crash, I noticed that my test library won't crash when run with Lua interpreter, but it would do so when running under my application (which loads a bunch of other libraries). If I just require "mylibrary", the crash won't happen.

Anyway, using WinDbg to get some stack traces, shows me that mylibrary is loaded here:
00000000`047b0000 00000000`047c4000   mylibrary C (private pdb symbols)  D:\symbols\mylibrary.pdb

And at address 0x047b104f I have this:
dt 047b104f
module_cleanup
 int  mylibrary!module_cleanup+0(
lua_State*)

When I close my application, the Lua state is closed and I got an access violation, with this stack trace: 

WARNING: Frame IP not in any known module. Following frames may be wrong.
0x47b104f
Lua5_1!luaD_precall+0x17d
Lua5_1!luaD_call+0x40
Lua5_1!GCTM+0xae
Lua5_1!luaC_callGCTM+0x14
Lua5_1!callallgcTM+0x9
Lua5_1!luaD_rawrunprotected+0x38
Lua5_1!lua_close+0x48
InconcertWebHandler!CLuaRuntime<CEvaluadorLua>::~CLuaRuntime<CEvaluadorLua>+0x28
InconcertWebHandler!CEvaluadorLua::~CEvaluadorLua+0x68
InconcertWebHandler!CEvaluadorLua::`scalar deleting destructor'+0xf
InconcertWebHandler!CSingleStatePool::DestroyState+0x38
InconcertWebHandler!CSingleStatePool::ReleaseStates+0x55
InconcertWebHandler!CSingleStatePool::~CSingleStatePool+0x34
InconcertWebHandler!CSingleStatePool::`scalar deleting destructor'+0xf
InconcertWebHandler!CWebServerInstance::~CWebServerInstance+0x89
InconcertWebHandler!CWebServerInstance::`scalar deleting destructor'+0xf
InconcertWebHandler!CServiceModule::Run+0x5b3
InconcertWebHandler!CServiceModule::Start+0x91
InconcertWebHandler!WinMain+0x30e

At that point, mylibrary was unloaded.

While this library is doing nothing fancy by itself, other libraries in the system are using a way to register that is using the environment.

static void InitializeBridge(lua_State* L, const char* libraryName, const luaL_Reg* reg = NULL)
{
// since we're setting an environment, we need to call through Lua to set it up
lua_pushcfunction(L, __ActualLibraryInitialization);
lua_pushstring(L, libraryName);
lua_pushlightuserdata(L, (void*)reg);
lua_call(L, 2, 1);
}

/**
Performs the actual initialization of the library. This function should only be called through InitializeBridge
*/
static int __ActualLibraryInitialization(lua_State* L) {
const char* libraryName = luaL_checkstring(L, 1);
luaL_checktype(L, 2, LUA_TLIGHTUSERDATA);
const luaL_Reg* reg = (const luaL_Reg*)lua_touserdata(L, 2);

static const struct luaL_reg dummy[] = {
{NULL, NULL},
};
// create a table and use it as the environment for this module
lua_newtable(L);
lua_replace(L, LUA_ENVIRONINDEX);
// register module functions. This leaves a table on top of the stack
if(reg) {
luaL_register(L, libraryName, reg);
}
else {
luaL_register(L, libraryName, dummy);
}
return 1;
}

Other libraries using this method to setup an environment do use the environment as a metatable for a sentinel data (which is used to tell when the library is unloaded). Is it possible that I'm mistakingly overriding the __gc method of another library?