lua-users home
lua-l archive

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




On Mon, Jun 27, 2011 at 3:02 PM, Peter Cawley <lua@corsix.org> wrote:
On Mon, Jun 27, 2011 at 1:57 PM, Gaspard Bucher <gaspard@teti.ch> wrote:
> This means that the required script gets the original global _ENV even
> though _LOADED._G has been changed. It can also read the first "foo".
>
> It seems that removing _LOADED._G is not enough to purge "foo"...

That would be because when a chunk is loaded, it is assigned as its
environment the value require"debug".getregistry()[2]. The environment
for your first chunk was from here, so unless changed, your second
chunk gets the same thing from here.

Thanks Moonlit master ! From the sources, index 2 in the registry is:

#define LUA_RIDX_GLOBALS 2

It's nice to know that the environment for loaded chunks comes from there. With this knew knowledge, I tried different scenarios to purge the global environment, and the only solution I found is either to set _ENV before setting "foo" and then removing the environment or to nil "foo":

===================== test4.lua
local print, collectgarbage = print, collectgarbage
local req = require "debug".getregistry()
local gc_mt = {}
function gc_mt.__gc(tbl)
  print('gc', tbl.name)
end
foo = {name='foo'}
setmetatable(foo,gc_mt)
_ENV = {}
req[2].foo = nil --- we cannot completely nil the global environment (error in __gc tag method (attempt to call a nil value)...

collectgarbage()  --- correctly garbage collects "foo"
print('end')
=====================

Gaspard