lua-users home
lua-l archive

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


sorry, gpm messed up the very important line with coroutine.resume() ;-)
try this:

weak = {}
setmetatable(weak, {__mode = "v"})

a = {}
b = coroutine.create(function(x) error() end)

coroutine.resume(b, a)
-- b still has "strong" reference to a
weak[b] = a

-- now there are no references to 'a' except the dead coroutine
a = nil
b = nil

-- the table has value of 'a' although noone is referring to it
collectgarbage("collect")
print(next(weak))

-- kill the value on dead's coroutine stack
a = next(weak)
print(coroutine.status(a))
debug.setlocal(a, 1, 1, "die hard")
collectgarbage("collect")

-- now the table is empty
print(next(weak))


On Thu, Nov 16, 2006 at 11:31:08PM +0100, Jerome Vuarand wrote:
> I don't understand your problem there. When I run your test, the first
> print displays nil, and coroutine.status throw an error because a is not
> a coroutine. That's the expected behaviour of that code.
> 
> Is there a bug on your platform, or did you expect a different behaviour
> ?
> 
> Karel Tuma wrote:
> > hello list,
> > 
> > recently i've spent few hours finding out "mysterious memory leaks"
> > in one erlang-like system written in lua.
> > 
> > some of you have probably been bitten by what i call "lua's weak
> > paradox", that is
> > 
> > http://lua-users.org/wiki/GarbageCollectingWeakTable
> > 
> > basically it means that weak element (either key or value) of 
> > a table wont
> > get garbage collected if there exists _any_ reachable strong 
> > path to that
> > value, including the strong part of the table row in question.
> > somehow, it's so wicked it actually sounds right.
> > naturally, from my experience i thought this applies only to 
> > tables with
> > either cyclic weak key or value, but still i got bitten by 
> > this "feature"
> > today:
> > 
> > weak = {}
> > setmetatable(weak, {__mode = "v"})
> > 
> > a = {}
> > b = coroutine.create(function(x) error() end)
> > 
> > -- b still has "strong" reference to a
> > weak[b] = a
> > 
> > -- now there are no references to 'a' except the dead coroutine
> > a = nil
> > b = nil
> > 
> > -- the table has value of 'a' although noone is referring to it
> > collectgarbage("collect")
> > print(next(weak))
> > 
> > -- kill the value on dead's coroutine stack
> > a = next(weak)
> > print(coroutine.status(a))
> > debug.setlocal(a, 1, 1, "die hard")
> > collectgarbage("collect")
> > 
> > -- now the table is empty
> > print(next(weak))
> > 
> > as you can see, there is something wrong with this. the "dead"
> > coroutine makes "strong" reference to 'a' but there is no way
> > to kill that reference in the first place. i'd understand this
> > if it would be open upvalue, or the coroutine alive, but come on,
> > what's purpose of completely dead coroutine's stack making strong
> > references to my weak values?
> > 
> > solution to this should be simple: ignore references from dead
> > coroutine's stack, i'm now trying to figure out how to hack this
> > into lua's gc (which is the most mysterious part of lua for me :)
> > the question is: will this break something? i know that coroutine's
> > upvalues should be left strong but i guess there will be also
> > something else because otherwise i dont see any rationale behind
> > this evil plot of coroutine walking zombies ;)
> > 
> > //kt