lua-users home
lua-l archive

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

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

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"

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

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

-- now the table is empty

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 ;)